blob: 5c5dfe1bf17dbb77e97b346546348cefd816ecfc [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
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001683using InputDispatcherDeathTest = InputDispatcherTest;
1684
1685/**
1686 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1687 * should crash.
1688 */
1689TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1690 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1691 ScopedSilentDeath _silentDeath;
1692
1693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1694 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1695 "Fake Window", ADISPLAY_ID_DEFAULT);
1696 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1697 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1698 "Incorrect WindowInfosUpdate provided");
1699}
1700
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001701TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1704 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001705
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001707 // Inject a MotionEvent to an unknown display.
1708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001709 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1711
1712 // Window should receive motion event.
1713 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1714}
1715
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 * Calling onWindowInfosChanged once should not cause any issues.
1718 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719 * called twice.
1720 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001721TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1724 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001725 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001729 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001730 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732
1733 // Window should receive motion event.
1734 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1735}
1736
1737/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001738 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001739 */
1740TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001742 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1743 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001744 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001745
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1747 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001749 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001750 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001752
1753 // Window should receive motion event.
1754 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1755}
1756
Arthur Hungb92218b2018-08-14 12:00:21 +08001757// The foreground window should receive the first touch down event.
1758TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001760 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001761 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001762 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001763 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001765 mDispatcher->onWindowInfosChanged(
1766 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001768 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001770
1771 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001772 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001773 windowSecond->assertNoEvents();
1774}
1775
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776/**
1777 * Two windows: A top window, and a wallpaper behind the window.
1778 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1779 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001780 * 1. foregroundWindow <-- dup touch to wallpaper
1781 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001782 */
1783TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1785 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001786 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001787 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001788 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001789 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001790 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001791
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001792 mDispatcher->onWindowInfosChanged(
1793 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001795 injectMotionEvent(*mDispatcher,
1796 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1797 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1798 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1800
1801 // Both foreground window and its wallpaper should receive the touch down
1802 foregroundWindow->consumeMotionDown();
1803 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1804
1805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001806 injectMotionEvent(*mDispatcher,
1807 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1808 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1809 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1811
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001812 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001813 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1814
1815 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001816 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001817 foregroundWindow->consumeMotionCancel();
1818 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1819 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1820}
1821
1822/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001823 * Two fingers down on the window, and lift off the first finger.
1824 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1825 * contains a single pointer.
1826 */
1827TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1829 sp<FakeWindowHandle> window =
1830 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1831
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001832 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001833 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1835 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1836 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001837 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001838 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1839 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1840 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1841 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001842 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001843 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1844 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1845 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1846 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001847 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1848 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1849 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1850
1851 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001852 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001853 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1854 window->consumeMotionEvent(
1855 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1856}
1857
1858/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1860 * with the following differences:
1861 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1862 * clean up the connection.
1863 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1864 * Ensure that there's no crash in the dispatcher.
1865 */
1866TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1868 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001869 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001870 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001871 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001872 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001873 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001874
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001875 mDispatcher->onWindowInfosChanged(
1876 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001878 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001879 {100, 200}))
1880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1881
1882 // Both foreground window and its wallpaper should receive the touch down
1883 foregroundWindow->consumeMotionDown();
1884 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1885
1886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001887 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001888 ADISPLAY_ID_DEFAULT, {110, 200}))
1889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1890
1891 foregroundWindow->consumeMotionMove();
1892 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1893
1894 // Wallpaper closes its channel, but the window remains.
1895 wallpaperWindow->destroyReceiver();
1896 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1897
1898 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1899 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001900 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001901 foregroundWindow->consumeMotionCancel();
1902}
1903
Arthur Hungc539dbb2022-12-08 07:45:36 +00001904class ShouldSplitTouchFixture : public InputDispatcherTest,
1905 public ::testing::WithParamInterface<bool> {};
1906INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1907 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001908/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909 * A single window that receives touch (on top), and a wallpaper window underneath it.
1910 * The top window gets a multitouch gesture.
1911 * Ensure that wallpaper gets the same gesture.
1912 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001913TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001915 sp<FakeWindowHandle> foregroundWindow =
1916 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1917 foregroundWindow->setDupTouchToWallpaper(true);
1918 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001919
1920 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001921 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001922 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001924 mDispatcher->onWindowInfosChanged(
1925 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001926
1927 // Touch down on top window
1928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001929 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001930 {100, 100}))
1931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1932
1933 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001934 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001935 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1936
1937 // Second finger down on the top window
1938 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001939 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001941 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1942 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943 .build();
1944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001945 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 InputEventInjectionSync::WAIT_FOR_RESULT))
1947 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1948
Harry Cutts33476232023-01-30 19:57:29 +00001949 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1950 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001951 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952
1953 const MotionEvent secondFingerUpEvent =
1954 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1955 .displayId(ADISPLAY_ID_DEFAULT)
1956 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001957 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1958 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001959 .build();
1960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001961 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001962 InputEventInjectionSync::WAIT_FOR_RESULT))
1963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1964 foregroundWindow->consumeMotionPointerUp(0);
1965 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1966
1967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001968 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001969 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1970 AINPUT_SOURCE_TOUCHSCREEN)
1971 .displayId(ADISPLAY_ID_DEFAULT)
1972 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001973 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001974 .x(100)
1975 .y(100))
1976 .build(),
1977 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1979 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1980 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981}
1982
1983/**
1984 * Two windows: a window on the left and window on the right.
1985 * A third window, wallpaper, is behind both windows, and spans both top windows.
1986 * The first touch down goes to the left window. A second pointer touches down on the right window.
1987 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1988 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1989 * ACTION_POINTER_DOWN(1).
1990 */
1991TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1992 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1993 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001994 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001996 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997
1998 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001999 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002001 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002002
2003 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002004 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002006 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002008 mDispatcher->onWindowInfosChanged(
2009 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2010 {},
2011 0,
2012 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013
2014 // Touch down on left window
2015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002016 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 {100, 100}))
2018 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2019
2020 // Both foreground window and its wallpaper should receive the touch down
2021 leftWindow->consumeMotionDown();
2022 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2023
2024 // Second finger down on the right window
2025 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002026 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002028 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2029 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 .build();
2031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002032 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 InputEventInjectionSync::WAIT_FOR_RESULT))
2034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2035
2036 leftWindow->consumeMotionMove();
2037 // Since the touch is split, right window gets ACTION_DOWN
2038 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002039 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 expectedWallpaperFlags);
2041
2042 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002043 mDispatcher->onWindowInfosChanged(
2044 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002045 leftWindow->consumeMotionCancel();
2046 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2047 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2048
2049 // The pointer that's still down on the right window moves, and goes to the right window only.
2050 // As far as the dispatcher's concerned though, both pointers are still present.
2051 const MotionEvent secondFingerMoveEvent =
2052 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2053 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002054 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2055 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002056 .build();
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002058 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002059 InputEventInjectionSync::WAIT_FOR_RESULT));
2060 rightWindow->consumeMotionMove();
2061
2062 leftWindow->assertNoEvents();
2063 rightWindow->assertNoEvents();
2064 wallpaperWindow->assertNoEvents();
2065}
2066
Arthur Hungc539dbb2022-12-08 07:45:36 +00002067/**
2068 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2069 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2070 * The right window should receive ACTION_DOWN.
2071 */
2072TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002074 sp<FakeWindowHandle> leftWindow =
2075 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2076 leftWindow->setFrame(Rect(0, 0, 200, 200));
2077 leftWindow->setDupTouchToWallpaper(true);
2078 leftWindow->setSlippery(true);
2079
2080 sp<FakeWindowHandle> rightWindow =
2081 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2082 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002083
2084 sp<FakeWindowHandle> wallpaperWindow =
2085 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2086 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002087
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002088 mDispatcher->onWindowInfosChanged(
2089 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2090 {},
2091 0,
2092 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002093
Arthur Hungc539dbb2022-12-08 07:45:36 +00002094 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002096 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002097 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002099
2100 // Both foreground window and its wallpaper should receive the touch down
2101 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002102 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2103
Arthur Hungc539dbb2022-12-08 07:45:36 +00002104 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002106 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002107 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2109
Arthur Hungc539dbb2022-12-08 07:45:36 +00002110 leftWindow->consumeMotionCancel();
2111 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2112 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002113}
2114
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002115/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002116 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2117 * interactive, it might stop sending this flag.
2118 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2119 * to have a consistent input stream.
2120 *
2121 * Test procedure:
2122 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2123 * DOWN (new gesture).
2124 *
2125 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2126 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2127 *
2128 * We technically just need a single window here, but we are using two windows (spy on top and a
2129 * regular window below) to emulate the actual situation where it happens on the device.
2130 */
2131TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2132 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2133 sp<FakeWindowHandle> spyWindow =
2134 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2135 spyWindow->setFrame(Rect(0, 0, 200, 200));
2136 spyWindow->setTrustedOverlay(true);
2137 spyWindow->setSpy(true);
2138
2139 sp<FakeWindowHandle> window =
2140 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2141 window->setFrame(Rect(0, 0, 200, 200));
2142
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002143 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002144 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002145
2146 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002147 mDispatcher->notifyMotion(
2148 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2149 .deviceId(touchDeviceId)
2150 .policyFlags(DEFAULT_POLICY_FLAGS)
2151 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2152 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002153
Prabir Pradhan678438e2023-04-13 19:32:51 +00002154 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2155 .deviceId(touchDeviceId)
2156 .policyFlags(DEFAULT_POLICY_FLAGS)
2157 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2158 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2159 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002160 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2161 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2162 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2163 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2164
2165 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002166 mDispatcher->notifyMotion(
2167 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2168 .deviceId(touchDeviceId)
2169 .policyFlags(0)
2170 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2171 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2172 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002173 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2174 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2175
2176 // We don't need to reset the device to reproduce the issue, but the reset event typically
2177 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002178 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002179
2180 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002181 mDispatcher->notifyMotion(
2182 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2183 .deviceId(touchDeviceId)
2184 .policyFlags(DEFAULT_POLICY_FLAGS)
2185 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2186 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002187 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2188 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2189
2190 // No more events
2191 spyWindow->assertNoEvents();
2192 window->assertNoEvents();
2193}
2194
2195/**
Linnan Li907ae732023-09-05 17:14:21 +08002196 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2197 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2198 * interactive, it might stop sending this flag.
2199 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2200 * the consistency of the hover event in this case.
2201 *
2202 * Test procedure:
2203 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2204 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2205 *
2206 * We expect to receive two full streams of hover events.
2207 */
2208TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2209 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2210
2211 sp<FakeWindowHandle> window =
2212 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2213 window->setFrame(Rect(0, 0, 300, 300));
2214
2215 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2216
2217 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2218 .policyFlags(DEFAULT_POLICY_FLAGS)
2219 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2220 .build());
2221 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2222
2223 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2224 .policyFlags(DEFAULT_POLICY_FLAGS)
2225 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2226 .build());
2227 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2228
2229 // Send hover exit without the default policy flags.
2230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2231 .policyFlags(0)
2232 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2233 .build());
2234
2235 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2236
2237 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2238 // right event.
2239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2240 .policyFlags(DEFAULT_POLICY_FLAGS)
2241 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2242 .build());
2243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2244
2245 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2246 .policyFlags(DEFAULT_POLICY_FLAGS)
2247 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2248 .build());
2249 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2250
2251 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2252 .policyFlags(DEFAULT_POLICY_FLAGS)
2253 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2254 .build());
2255 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2256}
2257
2258/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002259 * Two windows: a window on the left and a window on the right.
2260 * Mouse is hovered from the right window into the left window.
2261 * Next, we tap on the left window, where the cursor was last seen.
2262 * The second tap is done onto the right window.
2263 * The mouse and tap are from two different devices.
2264 * We technically don't need to set the downtime / eventtime for these events, but setting these
2265 * explicitly helps during debugging.
2266 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2267 * In the buggy implementation, a tap on the right window would cause a crash.
2268 */
2269TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2271 sp<FakeWindowHandle> leftWindow =
2272 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2273 leftWindow->setFrame(Rect(0, 0, 200, 200));
2274
2275 sp<FakeWindowHandle> rightWindow =
2276 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2277 rightWindow->setFrame(Rect(200, 0, 400, 200));
2278
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002279 mDispatcher->onWindowInfosChanged(
2280 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002281 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2282 // stale.
2283 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2284 const int32_t mouseDeviceId = 6;
2285 const int32_t touchDeviceId = 4;
2286 // Move the cursor from right
2287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2290 AINPUT_SOURCE_MOUSE)
2291 .deviceId(mouseDeviceId)
2292 .downTime(baseTime + 10)
2293 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 .build()));
2296 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2297
2298 // .. to the left window
2299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002300 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002301 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2302 AINPUT_SOURCE_MOUSE)
2303 .deviceId(mouseDeviceId)
2304 .downTime(baseTime + 10)
2305 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002306 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002307 .build()));
2308 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2309 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2310 // Now tap the left window
2311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002312 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002313 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2314 AINPUT_SOURCE_TOUCHSCREEN)
2315 .deviceId(touchDeviceId)
2316 .downTime(baseTime + 40)
2317 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002318 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002319 .build()));
2320 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2321 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2322
2323 // release tap
2324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2327 AINPUT_SOURCE_TOUCHSCREEN)
2328 .deviceId(touchDeviceId)
2329 .downTime(baseTime + 40)
2330 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 .build()));
2333 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2334
2335 // Tap the window on the right
2336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002338 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2339 AINPUT_SOURCE_TOUCHSCREEN)
2340 .deviceId(touchDeviceId)
2341 .downTime(baseTime + 60)
2342 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002343 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002344 .build()));
2345 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2346
2347 // release tap
2348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002349 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002350 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2351 AINPUT_SOURCE_TOUCHSCREEN)
2352 .deviceId(touchDeviceId)
2353 .downTime(baseTime + 60)
2354 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002355 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002356 .build()));
2357 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2358
2359 // No more events
2360 leftWindow->assertNoEvents();
2361 rightWindow->assertNoEvents();
2362}
2363
2364/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002365 * Start hovering in a window. While this hover is still active, make another window appear on top.
2366 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2367 * While the top window is present, the hovering is stopped.
2368 * Later, hovering gets resumed again.
2369 * Ensure that new hover gesture is handled correctly.
2370 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2371 * to the window that's currently being hovered over.
2372 */
2373TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2375 sp<FakeWindowHandle> window =
2376 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2377 window->setFrame(Rect(0, 0, 200, 200));
2378
2379 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002381
2382 // Start hovering in the window
2383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2384 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2385 .build());
2386 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2387
2388 // Now, an obscuring window appears!
2389 sp<FakeWindowHandle> obscuringWindow =
2390 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2391 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002392 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002393 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2394 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2395 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2396 obscuringWindow->setNoInputChannel(true);
2397 obscuringWindow->setFocusable(false);
2398 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002399 mDispatcher->onWindowInfosChanged(
2400 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002401
2402 // While this new obscuring window is present, the hovering is stopped
2403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2405 .build());
2406 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2407
2408 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002410
2411 // And a new hover gesture starts.
2412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2413 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2414 .build());
2415 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2416}
2417
2418/**
2419 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2420 * the obscuring window.
2421 */
2422TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2424 sp<FakeWindowHandle> window =
2425 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2426 window->setFrame(Rect(0, 0, 200, 200));
2427
2428 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002429 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002430
2431 // Start hovering in the window
2432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2433 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2434 .build());
2435 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2436
2437 // Now, an obscuring window appears!
2438 sp<FakeWindowHandle> obscuringWindow =
2439 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2440 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002441 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002442 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2443 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2444 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2445 obscuringWindow->setNoInputChannel(true);
2446 obscuringWindow->setFocusable(false);
2447 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002448 mDispatcher->onWindowInfosChanged(
2449 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002450
2451 // While this new obscuring window is present, the hovering continues. The event can't go to the
2452 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2455 .build());
2456 obscuringWindow->assertNoEvents();
2457 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2458
2459 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002460 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002461
2462 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2463 // so it should generate a HOVER_ENTER
2464 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2465 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2466 .build());
2467 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2468
2469 // Now the MOVE should be getting dispatched normally
2470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2471 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2472 .build());
2473 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2474}
2475
2476/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002477 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2478 * events are delivered to the window.
2479 */
2480TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2481 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2482 sp<FakeWindowHandle> window =
2483 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2484 window->setFrame(Rect(0, 0, 200, 200));
2485 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2486
2487 // Start hovering in the window
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2489 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2490 .build());
2491 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2492
2493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2494 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2495 .build());
2496 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2497
2498 // Scroll with the mouse
2499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2500 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2501 .build());
2502 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2503}
2504
2505using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2506
2507/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002508 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2509 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002510 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002511TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2513 sp<FakeWindowHandle> window =
2514 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2515 window->setFrame(Rect(0, 0, 200, 200));
2516
2517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2518
2519 constexpr int32_t touchDeviceId = 4;
2520 constexpr int32_t stylusDeviceId = 2;
2521
2522 // Stylus down
2523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2524 .deviceId(stylusDeviceId)
2525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2526 .build());
2527 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2528
2529 // Touch down
2530 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2531 .deviceId(touchDeviceId)
2532 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2533 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002534
2535 // Touch move
2536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2537 .deviceId(touchDeviceId)
2538 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2539 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002540 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002541
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002542 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2544 .deviceId(stylusDeviceId)
2545 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2546 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002547 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2548 WithCoords(101, 111)));
2549
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002550 window->assertNoEvents();
2551}
2552
2553/**
2554 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002555 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002556 * Similar test as above, but with added SPY window.
2557 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002558TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2560 sp<FakeWindowHandle> window =
2561 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2562 sp<FakeWindowHandle> spyWindow =
2563 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2564 spyWindow->setFrame(Rect(0, 0, 200, 200));
2565 spyWindow->setTrustedOverlay(true);
2566 spyWindow->setSpy(true);
2567 window->setFrame(Rect(0, 0, 200, 200));
2568
2569 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2570
2571 constexpr int32_t touchDeviceId = 4;
2572 constexpr int32_t stylusDeviceId = 2;
2573
2574 // Stylus down
2575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2576 .deviceId(stylusDeviceId)
2577 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2578 .build());
2579 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2580 spyWindow->consumeMotionEvent(
2581 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2582
2583 // Touch down
2584 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2585 .deviceId(touchDeviceId)
2586 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2587 .build());
2588
2589 // Touch move
2590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2591 .deviceId(touchDeviceId)
2592 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2593 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002594
2595 // Touch is ignored because stylus is already down
2596
2597 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2599 .deviceId(stylusDeviceId)
2600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2601 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002602 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2603 WithCoords(101, 111)));
2604 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2605 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002606
2607 window->assertNoEvents();
2608 spyWindow->assertNoEvents();
2609}
2610
2611/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002612 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002613 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002614 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002615TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2617 sp<FakeWindowHandle> window =
2618 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2619 window->setFrame(Rect(0, 0, 200, 200));
2620
2621 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2622
2623 constexpr int32_t touchDeviceId = 4;
2624 constexpr int32_t stylusDeviceId = 2;
2625
2626 // Stylus down on the window
2627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2628 .deviceId(stylusDeviceId)
2629 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2630 .build());
2631 window->consumeMotionEvent(
2632 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2633
2634 // Touch down on window
2635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2636 .deviceId(touchDeviceId)
2637 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2638 .build());
2639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2642 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002644 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002646 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2648 .deviceId(stylusDeviceId)
2649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2650 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002651 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2652 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002653
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002654 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2656 .deviceId(touchDeviceId)
2657 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2658 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002659 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002660}
2661
2662/**
2663 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002664 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002665 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002666TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2668 sp<FakeWindowHandle> window =
2669 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2670 window->setFrame(Rect(0, 0, 200, 200));
2671
2672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2673
2674 constexpr int32_t touchDeviceId = 4;
2675 constexpr int32_t stylusDeviceId = 2;
2676
2677 // Touch down on window
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2679 .deviceId(touchDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2681 .build());
2682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2683 .deviceId(touchDeviceId)
2684 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2685 .build());
2686 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2687 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2688
2689 // Stylus hover on the window
2690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2691 .deviceId(stylusDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2693 .build());
2694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2695 .deviceId(stylusDeviceId)
2696 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2697 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002698 // Stylus hover movement causes touch to be canceled
2699 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2700 WithCoords(141, 146)));
2701 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2702 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2703 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2704 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002705
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002706 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002707 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2708 .deviceId(touchDeviceId)
2709 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2710 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002711
2712 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002713}
2714
2715/**
2716 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2717 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2718 * become active.
2719 */
2720TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2722 sp<FakeWindowHandle> window =
2723 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2724 window->setFrame(Rect(0, 0, 200, 200));
2725
2726 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2727
2728 constexpr int32_t stylusDeviceId1 = 3;
2729 constexpr int32_t stylusDeviceId2 = 5;
2730
2731 // Touch down on window
2732 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2733 .deviceId(stylusDeviceId1)
2734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2735 .build());
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2737 .deviceId(stylusDeviceId1)
2738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2739 .build());
2740 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2741 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2742
2743 // Second stylus down
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2745 .deviceId(stylusDeviceId2)
2746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2747 .build());
2748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2749 .deviceId(stylusDeviceId2)
2750 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2751 .build());
2752
2753 // First stylus is canceled, second one takes over.
2754 window->consumeMotionEvent(
2755 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2756 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2757 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2758
2759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2760 .deviceId(stylusDeviceId1)
2761 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2762 .build());
2763 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002764 window->assertNoEvents();
2765}
2766
2767/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002768 * One window. Touch down on the window. Then, stylus down on the window from another device.
2769 * Ensure that is canceled, because stylus down should be preferred over touch.
2770 */
2771TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2773 sp<FakeWindowHandle> window =
2774 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2775 window->setFrame(Rect(0, 0, 200, 200));
2776
2777 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2778
2779 constexpr int32_t touchDeviceId = 4;
2780 constexpr int32_t stylusDeviceId = 2;
2781
2782 // Touch down on window
2783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2784 .deviceId(touchDeviceId)
2785 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2786 .build());
2787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2788 .deviceId(touchDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2790 .build());
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2792 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2793
2794 // Stylus down on the window
2795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2796 .deviceId(stylusDeviceId)
2797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2798 .build());
2799 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2800 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2801
2802 // Subsequent stylus movements are delivered correctly
2803 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2804 .deviceId(stylusDeviceId)
2805 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2806 .build());
2807 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2808 WithCoords(101, 111)));
2809}
2810
2811/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812 * Two windows: a window on the left and a window on the right.
2813 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2814 * down. Then, on the left window, also place second touch pointer down.
2815 * This test tries to reproduce a crash.
2816 * In the buggy implementation, second pointer down on the left window would cause a crash.
2817 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002818TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2820 sp<FakeWindowHandle> leftWindow =
2821 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2822 leftWindow->setFrame(Rect(0, 0, 200, 200));
2823
2824 sp<FakeWindowHandle> rightWindow =
2825 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2826 rightWindow->setFrame(Rect(200, 0, 400, 200));
2827
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002828 mDispatcher->onWindowInfosChanged(
2829 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830
2831 const int32_t touchDeviceId = 4;
2832 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002833
2834 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2836 .deviceId(mouseDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2838 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002839 leftWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2841
2842 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2844 .deviceId(mouseDeviceId)
2845 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2846 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2847 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002848
2849 leftWindow->consumeMotionEvent(
2850 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2851 leftWindow->consumeMotionEvent(
2852 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2853
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(
2855 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2856 .deviceId(mouseDeviceId)
2857 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2858 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2859 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2860 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2862
2863 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2865 .deviceId(touchDeviceId)
2866 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2867 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002868 leftWindow->assertNoEvents();
2869
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002870 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2871
2872 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2874 .deviceId(touchDeviceId)
2875 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2876 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2877 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002878 // Since this is now a new splittable pointer going down on the left window, and it's coming
2879 // from a different device, the current gesture in the left window (pointer down) should first
2880 // be canceled.
2881 leftWindow->consumeMotionEvent(
2882 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002883 leftWindow->consumeMotionEvent(
2884 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2885 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2886 // current implementation.
2887 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2888 rightWindow->consumeMotionEvent(
2889 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2890
2891 leftWindow->assertNoEvents();
2892 rightWindow->assertNoEvents();
2893}
2894
2895/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002896 * Two windows: a window on the left and a window on the right.
2897 * Mouse is hovered on the left window and stylus is hovered on the right window.
2898 */
2899TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2901 sp<FakeWindowHandle> leftWindow =
2902 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2903 leftWindow->setFrame(Rect(0, 0, 200, 200));
2904
2905 sp<FakeWindowHandle> rightWindow =
2906 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2907 rightWindow->setFrame(Rect(200, 0, 400, 200));
2908
2909 mDispatcher->onWindowInfosChanged(
2910 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2911
2912 const int32_t stylusDeviceId = 3;
2913 const int32_t mouseDeviceId = 6;
2914
2915 // Start hovering over the left window
2916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2917 .deviceId(mouseDeviceId)
2918 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2919 .build());
2920 leftWindow->consumeMotionEvent(
2921 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2922
2923 // Stylus hovered on right window
2924 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2925 .deviceId(stylusDeviceId)
2926 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2927 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002928 rightWindow->consumeMotionEvent(
2929 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2930
2931 // Subsequent HOVER_MOVE events are dispatched correctly.
2932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2933 .deviceId(mouseDeviceId)
2934 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2935 .build());
2936 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002937 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002938
2939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2940 .deviceId(stylusDeviceId)
2941 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2942 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002943 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002944 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002945
2946 leftWindow->assertNoEvents();
2947 rightWindow->assertNoEvents();
2948}
2949
2950/**
2951 * Three windows: a window on the left and a window on the right.
2952 * And a spy window that's positioned above all of them.
2953 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2954 * Check the stream that's received by the spy.
2955 */
2956TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2958
2959 sp<FakeWindowHandle> spyWindow =
2960 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2961 spyWindow->setFrame(Rect(0, 0, 400, 400));
2962 spyWindow->setTrustedOverlay(true);
2963 spyWindow->setSpy(true);
2964
2965 sp<FakeWindowHandle> leftWindow =
2966 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2967 leftWindow->setFrame(Rect(0, 0, 200, 200));
2968
2969 sp<FakeWindowHandle> rightWindow =
2970 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2971
2972 rightWindow->setFrame(Rect(200, 0, 400, 200));
2973
2974 mDispatcher->onWindowInfosChanged(
2975 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2976
2977 const int32_t stylusDeviceId = 1;
2978 const int32_t touchDeviceId = 2;
2979
2980 // Stylus down on the left window
2981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2982 .deviceId(stylusDeviceId)
2983 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2984 .build());
2985 leftWindow->consumeMotionEvent(
2986 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2987 spyWindow->consumeMotionEvent(
2988 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2989
2990 // Touch down on the right window
2991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2992 .deviceId(touchDeviceId)
2993 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2994 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002995 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002996 rightWindow->consumeMotionEvent(
2997 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002998
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002999 // Spy window does not receive touch events, because stylus events take precedence, and it
3000 // already has an active stylus gesture.
3001
3002 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3004 .deviceId(stylusDeviceId)
3005 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3006 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003007 leftWindow->consumeMotionEvent(
3008 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3009 spyWindow->consumeMotionEvent(
3010 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003011
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003012 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3014 .deviceId(touchDeviceId)
3015 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3016 .build());
3017 rightWindow->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003019
3020 spyWindow->assertNoEvents();
3021 leftWindow->assertNoEvents();
3022 rightWindow->assertNoEvents();
3023}
3024
3025/**
3026 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3027 * both.
3028 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003029 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003030 * At the same time, left and right should be getting independent streams of hovering and touch,
3031 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003032 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003033TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3035
3036 sp<FakeWindowHandle> spyWindow =
3037 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3038 spyWindow->setFrame(Rect(0, 0, 400, 400));
3039 spyWindow->setTrustedOverlay(true);
3040 spyWindow->setSpy(true);
3041
3042 sp<FakeWindowHandle> leftWindow =
3043 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3044 leftWindow->setFrame(Rect(0, 0, 200, 200));
3045
3046 sp<FakeWindowHandle> rightWindow =
3047 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3048 rightWindow->setFrame(Rect(200, 0, 400, 200));
3049
3050 mDispatcher->onWindowInfosChanged(
3051 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3052
3053 const int32_t stylusDeviceId = 1;
3054 const int32_t touchDeviceId = 2;
3055
3056 // Stylus hover on the left window
3057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3058 .deviceId(stylusDeviceId)
3059 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3060 .build());
3061 leftWindow->consumeMotionEvent(
3062 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3063 spyWindow->consumeMotionEvent(
3064 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3065
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003066 // Touch down on the right window. Spy doesn't receive this touch because it already has
3067 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3069 .deviceId(touchDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003073 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 rightWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3079 .deviceId(stylusDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3081 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003082 leftWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003084 spyWindow->consumeMotionEvent(
3085 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003086
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003087 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3089 .deviceId(touchDeviceId)
3090 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3091 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003092 rightWindow->consumeMotionEvent(
3093 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3094
3095 spyWindow->assertNoEvents();
3096 leftWindow->assertNoEvents();
3097 rightWindow->assertNoEvents();
3098}
3099
3100/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101 * On a single window, use two different devices: mouse and touch.
3102 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3103 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3104 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3105 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3106 * represent a new gesture.
3107 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003108TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3110 sp<FakeWindowHandle> window =
3111 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3112 window->setFrame(Rect(0, 0, 400, 400));
3113
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003114 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115
3116 const int32_t touchDeviceId = 4;
3117 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003119 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003120 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3121 .deviceId(touchDeviceId)
3122 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3123 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003125 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3126 .deviceId(touchDeviceId)
3127 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3128 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3129 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003130 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3132 .deviceId(touchDeviceId)
3133 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3134 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3137 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3138 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3139
3140 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3142 .deviceId(mouseDeviceId)
3143 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3144 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3145 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003146
3147 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003148 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3150
Prabir Pradhan678438e2023-04-13 19:32:51 +00003151 mDispatcher->notifyMotion(
3152 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3153 .deviceId(mouseDeviceId)
3154 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3155 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3156 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3157 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003158 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3159
3160 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003161 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3162 .deviceId(touchDeviceId)
3163 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3164 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3165 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003166 // Since we already canceled this touch gesture, it will be ignored until a completely new
3167 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3168 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3169 // However, mouse movements should continue to work.
3170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3171 .deviceId(mouseDeviceId)
3172 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3173 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3174 .build());
3175 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3176
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003177 window->assertNoEvents();
3178}
3179
3180/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003181 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3182 * the injected event.
3183 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003184TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3186 sp<FakeWindowHandle> window =
3187 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3188 window->setFrame(Rect(0, 0, 400, 400));
3189
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003190 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003191
3192 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003193 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3194 // completion.
3195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003196 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003197 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3198 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003199 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003200 .build()));
3201 window->consumeMotionEvent(
3202 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3203
3204 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3205 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3207 .deviceId(touchDeviceId)
3208 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3209 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003210
3211 window->consumeMotionEvent(
3212 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3213 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3214}
3215
3216/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003217 * This test is similar to the test above, but the sequence of injected events is different.
3218 *
3219 * Two windows: a window on the left and a window on the right.
3220 * Mouse is hovered over the left window.
3221 * Next, we tap on the left window, where the cursor was last seen.
3222 *
3223 * After that, we inject one finger down onto the right window, and then a second finger down onto
3224 * the left window.
3225 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3226 * window (first), and then another on the left window (second).
3227 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3228 * In the buggy implementation, second finger down on the left window would cause a crash.
3229 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003230TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003231 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3232 sp<FakeWindowHandle> leftWindow =
3233 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3234 leftWindow->setFrame(Rect(0, 0, 200, 200));
3235
3236 sp<FakeWindowHandle> rightWindow =
3237 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3238 rightWindow->setFrame(Rect(200, 0, 400, 200));
3239
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003240 mDispatcher->onWindowInfosChanged(
3241 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003242
3243 const int32_t mouseDeviceId = 6;
3244 const int32_t touchDeviceId = 4;
3245 // Hover over the left window. Keep the cursor there.
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_HOVER_ENTER,
3249 AINPUT_SOURCE_MOUSE)
3250 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3254
3255 // Tap on left window
3256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3259 AINPUT_SOURCE_TOUCHSCREEN)
3260 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003261 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003262 .build()));
3263
3264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003265 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003266 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3267 AINPUT_SOURCE_TOUCHSCREEN)
3268 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003270 .build()));
3271 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3272 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3273 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3274
3275 // First finger down on right window
3276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003277 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003278 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3279 AINPUT_SOURCE_TOUCHSCREEN)
3280 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003281 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003282 .build()));
3283 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3284
3285 // Second finger down on the left window
3286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003287 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003288 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3289 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003290 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3291 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003292 .build()));
3293 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3294 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3295
3296 // No more events
3297 leftWindow->assertNoEvents();
3298 rightWindow->assertNoEvents();
3299}
3300
3301/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003302 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3303 * While the touch is down, new hover events from the stylus device should be ignored. After the
3304 * touch is gone, stylus hovering should start working again.
3305 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003306TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3308 sp<FakeWindowHandle> window =
3309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3310 window->setFrame(Rect(0, 0, 200, 200));
3311
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313
3314 const int32_t stylusDeviceId = 5;
3315 const int32_t touchDeviceId = 4;
3316 // Start hovering with stylus
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003319 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003320 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003321 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003322 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003323 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003324
3325 // Finger down on the window
3326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003327 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003328 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003329 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003330 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003332 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003333
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003334 // Continue hovering with stylus.
3335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003336 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3338 AINPUT_SOURCE_STYLUS)
3339 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003340 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003341 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003342 // Hovers continue to work
3343 window->consumeMotionEvent(
3344 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345
3346 // Lift up the finger
3347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003348 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003349 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3350 AINPUT_SOURCE_TOUCHSCREEN)
3351 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003352 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003353 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003354
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003356 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003357 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3358 AINPUT_SOURCE_STYLUS)
3359 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003360 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003361 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003362 window->consumeMotionEvent(
3363 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003364 window->assertNoEvents();
3365}
3366
3367/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003368 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3369 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3370 *
3371 * Two windows: one on the left and one on the right.
3372 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3373 * Stylus down on the left window, and then touch down on the right window.
3374 * Check that the right window doesn't get touches while the stylus is down on the left window.
3375 */
3376TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3377 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3378 sp<FakeWindowHandle> leftWindow =
3379 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3380 ADISPLAY_ID_DEFAULT);
3381 leftWindow->setFrame(Rect(0, 0, 100, 100));
3382
3383 sp<FakeWindowHandle> sbtRightWindow =
3384 sp<FakeWindowHandle>::make(application, mDispatcher,
3385 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3386 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3387 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3388
3389 mDispatcher->onWindowInfosChanged(
3390 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3391
3392 const int32_t stylusDeviceId = 5;
3393 const int32_t touchDeviceId = 4;
3394
3395 // Stylus down in the left window
3396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3397 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3398 .deviceId(stylusDeviceId)
3399 .build());
3400 leftWindow->consumeMotionEvent(
3401 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3402
3403 // Finger tap on the right window
3404 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3405 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3406 .deviceId(touchDeviceId)
3407 .build());
3408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3409 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3410 .deviceId(touchDeviceId)
3411 .build());
3412
3413 // The touch should be blocked, because stylus is down somewhere else on screen!
3414 sbtRightWindow->assertNoEvents();
3415
3416 // Continue stylus motion, and ensure it's not impacted.
3417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3418 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3419 .deviceId(stylusDeviceId)
3420 .build());
3421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3422 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3423 .deviceId(stylusDeviceId)
3424 .build());
3425 leftWindow->consumeMotionEvent(
3426 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3427 leftWindow->consumeMotionEvent(
3428 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3429
3430 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3432 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3433 .deviceId(touchDeviceId)
3434 .build());
3435 sbtRightWindow->consumeMotionEvent(
3436 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3437}
3438
3439/**
3440 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3441 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3442 *
3443 * Two windows: one on the left and one on the right.
3444 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3445 * Stylus hover on the left window, and then touch down on the right window.
3446 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3447 */
3448TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3450 sp<FakeWindowHandle> leftWindow =
3451 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3452 ADISPLAY_ID_DEFAULT);
3453 leftWindow->setFrame(Rect(0, 0, 100, 100));
3454
3455 sp<FakeWindowHandle> sbtRightWindow =
3456 sp<FakeWindowHandle>::make(application, mDispatcher,
3457 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3458 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3459 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3460
3461 mDispatcher->onWindowInfosChanged(
3462 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3463
3464 const int32_t stylusDeviceId = 5;
3465 const int32_t touchDeviceId = 4;
3466
3467 // Stylus hover in the left window
3468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3469 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3470 .deviceId(stylusDeviceId)
3471 .build());
3472 leftWindow->consumeMotionEvent(
3473 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3474
3475 // Finger tap on the right window
3476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3477 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3478 .deviceId(touchDeviceId)
3479 .build());
3480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3481 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3482 .deviceId(touchDeviceId)
3483 .build());
3484
3485 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3486 sbtRightWindow->assertNoEvents();
3487
3488 // Continue stylus motion, and ensure it's not impacted.
3489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3490 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3491 .deviceId(stylusDeviceId)
3492 .build());
3493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3494 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3495 .deviceId(stylusDeviceId)
3496 .build());
3497 leftWindow->consumeMotionEvent(
3498 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3499 leftWindow->consumeMotionEvent(
3500 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3501
3502 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3504 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3505 .deviceId(touchDeviceId)
3506 .build());
3507 sbtRightWindow->consumeMotionEvent(
3508 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3509}
3510
3511/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003512 * A spy window above a window with no input channel.
3513 * Start hovering with a stylus device, and then tap with it.
3514 * Ensure spy window receives the entire sequence.
3515 */
3516TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3518 sp<FakeWindowHandle> spyWindow =
3519 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3520 spyWindow->setFrame(Rect(0, 0, 200, 200));
3521 spyWindow->setTrustedOverlay(true);
3522 spyWindow->setSpy(true);
3523 sp<FakeWindowHandle> window =
3524 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3525 window->setNoInputChannel(true);
3526 window->setFrame(Rect(0, 0, 200, 200));
3527
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003528 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003529
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003530 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3532 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3533 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003534 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3535 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, 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_EXIT));
3540
3541 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3544 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003545 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3546
3547 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3549 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3550 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003551 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3552
3553 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3556 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003557 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3558 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3560 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3561 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003562 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3563
3564 // No more events
3565 spyWindow->assertNoEvents();
3566 window->assertNoEvents();
3567}
3568
3569/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003570 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3571 * rejected. But since we already have an ongoing gesture, this event should be processed.
3572 * This prevents inconsistent events being handled inside the dispatcher.
3573 */
3574TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3576
3577 sp<FakeWindowHandle> window =
3578 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3579 window->setFrame(Rect(0, 0, 200, 200));
3580
3581 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3582
3583 // Start hovering with stylus
3584 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3585 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3586 .build());
3587 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3588
3589 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3591 .build();
3592 // Make this 'hoverExit' event stale
3593 mFakePolicy->setStaleEventTimeout(100ms);
3594 std::this_thread::sleep_for(100ms);
3595
3596 // It shouldn't be dropped by the dispatcher, even though it's stale.
3597 mDispatcher->notifyMotion(hoverExit);
3598 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3599
3600 // Stylus starts hovering again! There should be no crash.
3601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3602 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3603 .build());
3604 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3605}
3606
3607/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003608 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3609 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3610 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3611 * While the mouse is down, new move events from the touch device should be ignored.
3612 */
3613TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3614 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3615 sp<FakeWindowHandle> spyWindow =
3616 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3617 spyWindow->setFrame(Rect(0, 0, 200, 200));
3618 spyWindow->setTrustedOverlay(true);
3619 spyWindow->setSpy(true);
3620 sp<FakeWindowHandle> window =
3621 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3622 window->setFrame(Rect(0, 0, 200, 200));
3623
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003624 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003625
3626 const int32_t mouseDeviceId = 7;
3627 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003628
3629 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3631 .deviceId(mouseDeviceId)
3632 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3633 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003634 spyWindow->consumeMotionEvent(
3635 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3636 window->consumeMotionEvent(
3637 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3638
3639 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3641 .deviceId(touchDeviceId)
3642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3643 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003644 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3645 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3646 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3647 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3648
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3650 .deviceId(touchDeviceId)
3651 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3652 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003653 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3654 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3655
3656 // Pilfer the stream
3657 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3658 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3659
Prabir Pradhan678438e2023-04-13 19:32:51 +00003660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3661 .deviceId(touchDeviceId)
3662 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3663 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003664 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3665
3666 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003667 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3668 .deviceId(mouseDeviceId)
3669 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3670 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3671 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003672
3673 spyWindow->consumeMotionEvent(
3674 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3675 spyWindow->consumeMotionEvent(
3676 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3678
Prabir Pradhan678438e2023-04-13 19:32:51 +00003679 mDispatcher->notifyMotion(
3680 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3681 .deviceId(mouseDeviceId)
3682 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3683 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3684 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3685 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003686 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3687 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3688
3689 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3691 .deviceId(mouseDeviceId)
3692 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3693 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3694 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003695 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3696 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3697
3698 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003699 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3700 .deviceId(touchDeviceId)
3701 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3702 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003703
3704 // No more events
3705 spyWindow->assertNoEvents();
3706 window->assertNoEvents();
3707}
3708
3709/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003710 * On the display, have a single window, and also an area where there's no window.
3711 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3712 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3713 */
3714TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3716 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003717 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003718
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003719 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003720
3721 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003722 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003723
3724 mDispatcher->waitForIdle();
3725 window->assertNoEvents();
3726
3727 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003728 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003729 mDispatcher->waitForIdle();
3730 window->consumeMotionDown();
3731}
3732
3733/**
3734 * Same test as above, but instead of touching the empty space, the first touch goes to
3735 * non-touchable window.
3736 */
3737TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3739 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003740 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003741 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3742 window1->setTouchable(false);
3743 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003744 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003745 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3746
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003747 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003748
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003749 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003750 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003751
3752 mDispatcher->waitForIdle();
3753 window1->assertNoEvents();
3754 window2->assertNoEvents();
3755
3756 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003758 mDispatcher->waitForIdle();
3759 window2->consumeMotionDown();
3760}
3761
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003762/**
3763 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3764 * to the event time of the first ACTION_DOWN sent to the particular window.
3765 */
3766TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3768 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003769 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003770 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3771 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003773 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003775 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003776
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003777 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003779
3780 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003781
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003782 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003783 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003784 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3785 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003786
3787 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003789 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003790 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3791 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003792 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003793 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003794
3795 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003796 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003797 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003798 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003799
3800 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003801 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003802 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003803 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003804
3805 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3806 window1->consumeMotionMove();
3807 window1->assertNoEvents();
3808
3809 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003810 mDispatcher->notifyMotion(
3811 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003812 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003813 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003814
Prabir Pradhan678438e2023-04-13 19:32:51 +00003815 mDispatcher->notifyMotion(
3816 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003817 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003818 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003819}
3820
Garfield Tandf26e862020-07-01 20:18:19 -07003821TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003823 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003824 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003825 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003826 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003827 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003828 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003829
3830 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3831
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003832 mDispatcher->onWindowInfosChanged(
3833 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003834
3835 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003837 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003838 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3839 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003841 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003842 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003843
3844 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003846 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003847 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3848 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003849 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003850 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003851 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3852 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003853
3854 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003856 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003857 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3858 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003859 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003860 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003861 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3862 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003863
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003865 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003866 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3867 AINPUT_SOURCE_MOUSE)
3868 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3869 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
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()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003872 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003873
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003875 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003876 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3877 AINPUT_SOURCE_MOUSE)
3878 .buttonState(0)
3879 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003880 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003881 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003882 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003883
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003885 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003886 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3887 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003888 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003889 .build()));
3890 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3891
3892 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003894 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003895 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3896 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003897 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003898 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003899 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003900
3901 // No more events
3902 windowLeft->assertNoEvents();
3903 windowRight->assertNoEvents();
3904}
3905
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003906/**
3907 * Put two fingers down (and don't release them) and click the mouse button.
3908 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3909 * currently active gesture should be canceled, and the new one should proceed.
3910 */
3911TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3913 sp<FakeWindowHandle> window =
3914 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3915 window->setFrame(Rect(0, 0, 600, 800));
3916
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003917 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003918
3919 const int32_t touchDeviceId = 4;
3920 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003921
3922 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3924 .deviceId(touchDeviceId)
3925 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3926 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003927
Prabir Pradhan678438e2023-04-13 19:32:51 +00003928 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3929 .deviceId(touchDeviceId)
3930 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3931 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3932 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003933 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3934 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3935
3936 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3938 .deviceId(mouseDeviceId)
3939 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3941 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003942 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3943 WithPointerCount(2u)));
3944 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3945
Prabir Pradhan678438e2023-04-13 19:32:51 +00003946 mDispatcher->notifyMotion(
3947 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3948 .deviceId(mouseDeviceId)
3949 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3950 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3951 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3952 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003953 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3954
3955 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3956 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3958 .deviceId(touchDeviceId)
3959 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3960 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3961 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003962 window->assertNoEvents();
3963}
3964
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3967
3968 sp<FakeWindowHandle> spyWindow =
3969 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3970 spyWindow->setFrame(Rect(0, 0, 600, 800));
3971 spyWindow->setTrustedOverlay(true);
3972 spyWindow->setSpy(true);
3973 sp<FakeWindowHandle> window =
3974 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3975 window->setFrame(Rect(0, 0, 600, 800));
3976
3977 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003978 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003979
3980 // Send mouse cursor to the window
3981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003982 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003983 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3984 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003985 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003986 .build()));
3987
3988 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3989 WithSource(AINPUT_SOURCE_MOUSE)));
3990 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3991 WithSource(AINPUT_SOURCE_MOUSE)));
3992
3993 window->assertNoEvents();
3994 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003995}
3996
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003997TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3999
4000 sp<FakeWindowHandle> spyWindow =
4001 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4002 spyWindow->setFrame(Rect(0, 0, 600, 800));
4003 spyWindow->setTrustedOverlay(true);
4004 spyWindow->setSpy(true);
4005 sp<FakeWindowHandle> window =
4006 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4007 window->setFrame(Rect(0, 0, 600, 800));
4008
4009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004010 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004011
4012 // Send mouse cursor to the window
4013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004014 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004015 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4016 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004017 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004018 .build()));
4019
4020 // Move mouse cursor
4021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004022 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004023 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4024 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004026 .build()));
4027
4028 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4029 WithSource(AINPUT_SOURCE_MOUSE)));
4030 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4031 WithSource(AINPUT_SOURCE_MOUSE)));
4032 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4033 WithSource(AINPUT_SOURCE_MOUSE)));
4034 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4035 WithSource(AINPUT_SOURCE_MOUSE)));
4036 // Touch down on the window
4037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004038 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004039 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4040 AINPUT_SOURCE_TOUCHSCREEN)
4041 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004042 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004043 .build()));
4044 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4045 WithSource(AINPUT_SOURCE_MOUSE)));
4046 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4047 WithSource(AINPUT_SOURCE_MOUSE)));
4048 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4049 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4050 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4051 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4052
4053 // pilfer the motion, retaining the gesture on the spy window.
4054 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4055 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4056 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4057
4058 // Touch UP on the window
4059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004060 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004061 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4062 AINPUT_SOURCE_TOUCHSCREEN)
4063 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004064 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004065 .build()));
4066 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4067 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4068
4069 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4070 // to send a new gesture. It should again go to both windows (spy and the window below), just
4071 // like the first gesture did, before pilfering. The window configuration has not changed.
4072
4073 // One more tap - DOWN
4074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004075 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004076 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4077 AINPUT_SOURCE_TOUCHSCREEN)
4078 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004079 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004080 .build()));
4081 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4082 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4083 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4084 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4085
4086 // Touch UP on the window
4087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004088 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004089 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4090 AINPUT_SOURCE_TOUCHSCREEN)
4091 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004092 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004093 .build()));
4094 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4095 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4096 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4097 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4098
4099 window->assertNoEvents();
4100 spyWindow->assertNoEvents();
4101}
4102
Garfield Tandf26e862020-07-01 20:18:19 -07004103// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4104// directly in this test.
4105TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004107 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004108 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004109 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004110
4111 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4112
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004113 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004114
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004116 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004117 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4118 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004119 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004120 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004121 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004122 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004124 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004125 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4126 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004127 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004128 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004129 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4130 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004131
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004133 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004134 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4135 AINPUT_SOURCE_MOUSE)
4136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4137 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
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()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004140 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004141
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004144 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4145 AINPUT_SOURCE_MOUSE)
4146 .buttonState(0)
4147 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
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 Vishniakou5cee1e32022-11-29 12:35:39 -08004150 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004151
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004153 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004154 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4155 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004156 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004157 .build()));
4158 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4159
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004160 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4161 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4162 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004163 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004164 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4165 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004167 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004168 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004169}
4170
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004171/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004172 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4173 * is generated.
4174 */
4175TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4177 sp<FakeWindowHandle> window =
4178 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4179 window->setFrame(Rect(0, 0, 1200, 800));
4180
4181 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004184
4185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004186 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004187 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4188 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004190 .build()));
4191 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4192
4193 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004194 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004195 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4196}
4197
4198/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004199 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4200 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004201TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4202 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4203 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004204 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4205 sp<FakeWindowHandle> window =
4206 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4207 window->setFrame(Rect(0, 0, 1200, 800));
4208
4209 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4210
4211 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4212
4213 MotionEventBuilder hoverEnterBuilder =
4214 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4215 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4216 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4218 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4220 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4221 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4222 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4223}
4224
4225/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004226 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4227 */
4228TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4230 sp<FakeWindowHandle> window =
4231 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4232 window->setFrame(Rect(0, 0, 100, 100));
4233
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004235
4236 const int32_t mouseDeviceId = 7;
4237 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004238
4239 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4241 .deviceId(mouseDeviceId)
4242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4243 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004244 window->consumeMotionEvent(
4245 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4246
4247 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004248 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4249 .deviceId(touchDeviceId)
4250 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4251 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004252
4253 window->consumeMotionEvent(
4254 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4255 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4256}
4257
4258/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004259 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004260 * The tap causes a HOVER_EXIT event to be generated because the current event
4261 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004262 */
4263TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4265 sp<FakeWindowHandle> window =
4266 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4267 window->setFrame(Rect(0, 0, 100, 100));
4268
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004269 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4271 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4272 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004273 ASSERT_NO_FATAL_FAILURE(
4274 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4275 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004276
4277 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4279 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4280 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004281 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004282 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4283 WithSource(AINPUT_SOURCE_MOUSE))));
4284
4285 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004286 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4287 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4288
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004289 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4290 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4291 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004292 ASSERT_NO_FATAL_FAILURE(
4293 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4294 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4295}
4296
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004297TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4299 sp<FakeWindowHandle> windowDefaultDisplay =
4300 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4301 ADISPLAY_ID_DEFAULT);
4302 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4303 sp<FakeWindowHandle> windowSecondDisplay =
4304 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4305 SECOND_DISPLAY_ID);
4306 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4307
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004308 mDispatcher->onWindowInfosChanged(
4309 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004310
4311 // Set cursor position in window in default display and check that hover enter and move
4312 // events are generated.
4313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004314 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004315 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4316 AINPUT_SOURCE_MOUSE)
4317 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004318 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004319 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004320 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004321
4322 // Remove all windows in secondary display and check that no event happens on window in
4323 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004324 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4325
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004326 windowDefaultDisplay->assertNoEvents();
4327
4328 // Move cursor position in window in default display and check that only hover move
4329 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004330 mDispatcher->onWindowInfosChanged(
4331 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004333 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004334 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4335 AINPUT_SOURCE_MOUSE)
4336 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004337 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004338 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004339 windowDefaultDisplay->consumeMotionEvent(
4340 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4341 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004342 windowDefaultDisplay->assertNoEvents();
4343}
4344
Garfield Tan00f511d2019-06-12 16:55:40 -07004345TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004346 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004347
4348 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004349 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004350 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004351 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004352 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004353 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004354
4355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004357 mDispatcher->onWindowInfosChanged(
4358 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004359
4360 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4361 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004363 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004364 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004365 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004366 windowRight->assertNoEvents();
4367}
4368
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004369TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4372 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004373 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004374
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004376 setFocusedWindow(window);
4377
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004378 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004379
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004381
4382 // Window should receive key down event.
4383 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4384
4385 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4386 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004387 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004388 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004389}
4390
4391TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004392 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004393 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4394 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004395
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004396 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004397
Prabir Pradhan678438e2023-04-13 19:32:51 +00004398 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4399 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004400
4401 // Window should receive motion down event.
4402 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4403
4404 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4405 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004406 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004407 window->consumeMotionEvent(
4408 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004409}
4410
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004411TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4413 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4414 "Fake Window", ADISPLAY_ID_DEFAULT);
4415
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004416 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004417
4418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4419 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4420 .build());
4421
4422 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4423
4424 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4425 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4426 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4427
4428 // After the device has been reset, a new hovering stream can be sent to the window
4429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4431 .build());
4432 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4433}
4434
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004435TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4436 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004437 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4438 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004439 window->setFocusable(true);
4440
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004442 setFocusedWindow(window);
4443
4444 window->consumeFocusEvent(true);
4445
Prabir Pradhan678438e2023-04-13 19:32:51 +00004446 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004447 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4448 const nsecs_t injectTime = keyArgs.eventTime;
4449 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004450 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004451 // The dispatching time should be always greater than or equal to intercept key timeout.
4452 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4453 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4454 std::chrono::nanoseconds(interceptKeyTimeout).count());
4455}
4456
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004457/**
4458 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4459 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004460TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4461 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004462 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4463 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004464 window->setFocusable(true);
4465
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004466 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004467 setFocusedWindow(window);
4468
4469 window->consumeFocusEvent(true);
4470
Prabir Pradhan678438e2023-04-13 19:32:51 +00004471 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004472 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004473
4474 // Set a value that's significantly larger than the default consumption timeout. If the
4475 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4476 mFakePolicy->setInterceptKeyTimeout(600ms);
4477 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4478 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004479 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4480}
4481
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004482/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004483 * Two windows. First is a regular window. Second does not overlap with the first, and has
4484 * WATCH_OUTSIDE_TOUCH.
4485 * Both windows are owned by the same UID.
4486 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4487 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4488 */
4489TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004491 sp<FakeWindowHandle> window =
4492 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004493 window->setFrame(Rect{0, 0, 100, 100});
4494
4495 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004496 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004497 ADISPLAY_ID_DEFAULT);
4498 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4499 outsideWindow->setWatchOutsideTouch(true);
4500 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004501 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004502
4503 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004504 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4505 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4506 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004507 window->consumeMotionDown();
4508 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4509 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4510 outsideWindow->consumeMotionEvent(
4511 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004512
4513 // Ensure outsideWindow doesn't get any more events for the gesture.
4514 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4515 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4516 window->consumeMotionMove();
4517 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004518}
4519
4520/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004521 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4522 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4523 * ACTION_OUTSIDE event is sent per gesture.
4524 */
4525TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4526 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004528 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4529 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004530 window->setWatchOutsideTouch(true);
4531 window->setFrame(Rect{0, 0, 100, 100});
4532 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004533 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4534 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004535 secondWindow->setFrame(Rect{100, 100, 200, 200});
4536 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004537 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4538 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004539 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004540 mDispatcher->onWindowInfosChanged(
4541 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004542
4543 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004544 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4545 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4546 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004547 window->assertNoEvents();
4548 secondWindow->assertNoEvents();
4549
4550 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4551 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004552 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4553 ADISPLAY_ID_DEFAULT,
4554 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004555 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4556 window->consumeMotionEvent(
4557 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004558 secondWindow->consumeMotionDown();
4559 thirdWindow->assertNoEvents();
4560
4561 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4562 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004563 mDispatcher->notifyMotion(
4564 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4565 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004566 window->assertNoEvents();
4567 secondWindow->consumeMotionMove();
4568 thirdWindow->consumeMotionDown();
4569}
4570
Prabir Pradhan814fe082022-07-22 20:22:18 +00004571TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004573 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4574 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004575 window->setFocusable(true);
4576
Patrick Williamsd828f302023-04-28 17:52:08 -05004577 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004578 setFocusedWindow(window);
4579
4580 window->consumeFocusEvent(true);
4581
Prabir Pradhan678438e2023-04-13 19:32:51 +00004582 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4583 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4584 mDispatcher->notifyKey(keyDown);
4585 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004586
4587 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4588 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4589
4590 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004591 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004592
4593 window->consumeFocusEvent(false);
4594
Prabir Pradhan678438e2023-04-13 19:32:51 +00004595 mDispatcher->notifyKey(keyDown);
4596 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004597 window->assertNoEvents();
4598}
4599
Arthur Hung96483742022-11-15 03:30:48 +00004600TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4602 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4603 "Fake Window", ADISPLAY_ID_DEFAULT);
4604 // Ensure window is non-split and have some transform.
4605 window->setPreventSplitting(true);
4606 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004607 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004608
4609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004610 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004611 {50, 50}))
4612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4613 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4614
4615 const MotionEvent secondFingerDownEvent =
4616 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4617 .displayId(ADISPLAY_ID_DEFAULT)
4618 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004619 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4620 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004621 .build();
4622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004623 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004624 InputEventInjectionSync::WAIT_FOR_RESULT))
4625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4626
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004627 const MotionEvent& event = window->consumeMotionEvent();
4628 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4629 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4630 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4631 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4632 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004633}
4634
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004635/**
4636 * Two windows: a splittable and a non-splittable.
4637 * The non-splittable window shouldn't receive any "incomplete" gestures.
4638 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4639 * The second pointer should be dropped because the initial window is splittable, so it won't get
4640 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4641 * "incomplete" gestures.
4642 */
4643TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4645 sp<FakeWindowHandle> leftWindow =
4646 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4647 ADISPLAY_ID_DEFAULT);
4648 leftWindow->setPreventSplitting(false);
4649 leftWindow->setFrame(Rect(0, 0, 100, 100));
4650 sp<FakeWindowHandle> rightWindow =
4651 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4652 ADISPLAY_ID_DEFAULT);
4653 rightWindow->setPreventSplitting(true);
4654 rightWindow->setFrame(Rect(100, 100, 200, 200));
4655 mDispatcher->onWindowInfosChanged(
4656 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4657
4658 // Touch down on left, splittable window
4659 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4660 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4661 .build());
4662 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4663
4664 mDispatcher->notifyMotion(
4665 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4667 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4668 .build());
4669 leftWindow->assertNoEvents();
4670 rightWindow->assertNoEvents();
4671}
4672
Harry Cuttsb166c002023-05-09 13:06:05 +00004673TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4675 sp<FakeWindowHandle> window =
4676 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4677 window->setFrame(Rect(0, 0, 400, 400));
4678 sp<FakeWindowHandle> trustedOverlay =
4679 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4680 ADISPLAY_ID_DEFAULT);
4681 trustedOverlay->setSpy(true);
4682 trustedOverlay->setTrustedOverlay(true);
4683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004684 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004685
4686 // Start a three-finger touchpad swipe
4687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4688 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4689 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4690 .build());
4691 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4692 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4693 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4694 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4695 .build());
4696 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4697 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4698 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4699 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4700 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4701 .build());
4702
4703 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4704 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4705 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4706
4707 // Move the swipe a bit
4708 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4709 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4710 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4711 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4712 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4713 .build());
4714
4715 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4716
4717 // End the swipe
4718 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4719 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4720 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4721 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4722 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4723 .build());
4724 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4725 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4726 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4727 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4728 .build());
4729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4730 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4731 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4732 .build());
4733
4734 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4735 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4736 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4737
4738 window->assertNoEvents();
4739}
4740
4741TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4743 sp<FakeWindowHandle> window =
4744 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4745 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004747
4748 // Start a three-finger touchpad swipe
4749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4750 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4751 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4752 .build());
4753 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4754 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4755 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4756 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4757 .build());
4758 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4759 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4760 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4761 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4762 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4763 .build());
4764
4765 // Move the swipe a bit
4766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4767 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4768 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4769 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4770 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4771 .build());
4772
4773 // End the swipe
4774 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4775 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4776 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4777 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4778 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4779 .build());
4780 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4781 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4782 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4783 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4784 .build());
4785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4786 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4787 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4788 .build());
4789
4790 window->assertNoEvents();
4791}
4792
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004793/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004794 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4795 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004796 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004797 */
4798TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4800 sp<FakeWindowHandle> window =
4801 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4802 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004803 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004804
4805 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4807 .downTime(baseTime + 10)
4808 .eventTime(baseTime + 10)
4809 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4810 .build());
4811
4812 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4813
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004814 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004815 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004816
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004817 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004818
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004819 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4820 .downTime(baseTime + 10)
4821 .eventTime(baseTime + 30)
4822 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4823 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4824 .build());
4825
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004826 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4827
4828 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004829 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4830 .downTime(baseTime + 10)
4831 .eventTime(baseTime + 40)
4832 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4833 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4834 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004835
4836 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4837
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4839 .downTime(baseTime + 10)
4840 .eventTime(baseTime + 50)
4841 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4842 .build());
4843
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004844 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4845
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4847 .downTime(baseTime + 60)
4848 .eventTime(baseTime + 60)
4849 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4850 .build());
4851
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004852 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004853}
4854
4855/**
Hu Guo771a7692023-09-17 20:51:08 +08004856 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4857 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4858 * its coordinates should be converted by the transform of the windows of target screen.
4859 */
4860TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4861 // This case will create a window and a spy window on the default display and mirror
4862 // window on the second display. cancel event is sent through spy window pilferPointers
4863 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4864
4865 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4866 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4867 spyWindowDefaultDisplay->setTrustedOverlay(true);
4868 spyWindowDefaultDisplay->setSpy(true);
4869
4870 sp<FakeWindowHandle> windowDefaultDisplay =
4871 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4872 ADISPLAY_ID_DEFAULT);
4873 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4874
4875 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4876 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4877
4878 // Add the windows to the dispatcher
4879 mDispatcher->onWindowInfosChanged(
4880 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4881 *windowSecondDisplay->getInfo()},
4882 {},
4883 0,
4884 0});
4885
4886 // Send down to ADISPLAY_ID_DEFAULT
4887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4888 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4889 {100, 100}))
4890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4891
4892 spyWindowDefaultDisplay->consumeMotionDown();
4893 windowDefaultDisplay->consumeMotionDown();
4894
4895 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4896
4897 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004898 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4899 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004900
4901 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4902 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4903 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4904 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004905 EXPECT_EQ(100, event.getX(0));
4906 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004907}
4908
4909/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004910 * Ensure the correct coordinate spaces are used by InputDispatcher.
4911 *
4912 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4913 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4914 * space.
4915 */
4916class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4917public:
4918 void SetUp() override {
4919 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004920 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004921 }
4922
4923 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4924 gui::DisplayInfo info;
4925 info.displayId = displayId;
4926 info.transform = transform;
4927 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004928 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004929 }
4930
4931 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4932 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004933 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004934 }
4935
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004936 void removeAllWindowsAndDisplays() {
4937 mDisplayInfos.clear();
4938 mWindowInfos.clear();
4939 }
4940
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004941 // Set up a test scenario where the display has a scaled projection and there are two windows
4942 // on the display.
4943 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4944 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4945 // respectively.
4946 ui::Transform displayTransform;
4947 displayTransform.set(2, 0, 0, 4);
4948 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4949
4950 std::shared_ptr<FakeApplicationHandle> application =
4951 std::make_shared<FakeApplicationHandle>();
4952
4953 // Add two windows to the display. Their frames are represented in the display space.
4954 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004955 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4956 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004957 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4958 addWindow(firstWindow);
4959
4960 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004961 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4962 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004963 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4964 addWindow(secondWindow);
4965 return {std::move(firstWindow), std::move(secondWindow)};
4966 }
4967
4968private:
4969 std::vector<gui::DisplayInfo> mDisplayInfos;
4970 std::vector<gui::WindowInfo> mWindowInfos;
4971};
4972
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004973TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004974 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4975 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004976 // selected so that if the hit test was performed with the point and the bounds being in
4977 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004978 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4979 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4980 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004981
4982 firstWindow->consumeMotionDown();
4983 secondWindow->assertNoEvents();
4984}
4985
4986// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4987// the event should be treated as being in the logical display space.
4988TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4989 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4990 // Send down to the first window. The point is represented in the logical display space. The
4991 // point is selected so that if the hit test was done in logical display space, then it would
4992 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004993 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004994 PointF{75 * 2, 55 * 4});
4995
4996 firstWindow->consumeMotionDown();
4997 secondWindow->assertNoEvents();
4998}
4999
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005000// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5001// event should be treated as being in the logical display space.
5002TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5003 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5004
5005 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5006 ui::Transform injectedEventTransform;
5007 injectedEventTransform.set(matrix);
5008 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5009 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5010
5011 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5012 .displayId(ADISPLAY_ID_DEFAULT)
5013 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005014 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005015 .x(untransformedPoint.x)
5016 .y(untransformedPoint.y))
5017 .build();
5018 event.transform(matrix);
5019
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005020 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005021 InputEventInjectionSync::WAIT_FOR_RESULT);
5022
5023 firstWindow->consumeMotionDown();
5024 secondWindow->assertNoEvents();
5025}
5026
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005027TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5028 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5029
5030 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005031 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5032 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5033 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005034
5035 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005036 const MotionEvent& event = secondWindow->consumeMotionEvent();
5037 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005038
5039 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005040 EXPECT_EQ(300, event.getRawX(0));
5041 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005042
5043 // Ensure that the x and y values are in the window's coordinate space.
5044 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5045 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005046 EXPECT_EQ(100, event.getX(0));
5047 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005048}
5049
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005050TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5051 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5052 // The monitor will always receive events in the logical display's coordinate space, because
5053 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005054 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005055
5056 // Send down to the first window.
5057 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5058 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5059 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5060 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5061
5062 // Second pointer goes down on second window.
5063 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5064 ADISPLAY_ID_DEFAULT,
5065 {PointF{50, 100}, PointF{150, 220}}));
5066 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5067 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5068 {1, PointF{300, 880}}};
5069 monitor.consumeMotionEvent(
5070 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5071
5072 mDispatcher->cancelCurrentTouch();
5073
5074 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5075 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5076 monitor.consumeMotionEvent(
5077 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5078}
5079
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005080TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5081 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5082
5083 // Send down to the first window.
5084 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5085 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5086 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5087
5088 // The pointer is transferred to the second window, and the second window receives it in the
5089 // correct coordinate space.
5090 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5091 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5092 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5093}
5094
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005095TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5096 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5097
5098 // Send hover move to the second window, and ensure it shows up as hover enter.
5099 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5100 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5101 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5102 WithCoords(100, 80), WithRawCoords(300, 880)));
5103
5104 // Touch down at the same location and ensure a hover exit is synthesized.
5105 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5106 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5107 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5108 WithRawCoords(300, 880)));
5109 secondWindow->consumeMotionEvent(
5110 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5111 secondWindow->assertNoEvents();
5112 firstWindow->assertNoEvents();
5113}
5114
Prabir Pradhan453ae732023-10-13 14:30:14 +00005115// Same as above, but while the window is being mirrored.
5116TEST_F(InputDispatcherDisplayProjectionTest,
5117 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5118 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5119
5120 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5121 ui::Transform secondDisplayTransform;
5122 secondDisplayTransform.set(matrix);
5123 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5124
5125 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5126 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5127 addWindow(secondWindowClone);
5128
5129 // Send hover move to the second window, and ensure it shows up as hover enter.
5130 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5131 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5132 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5133 WithCoords(100, 80), WithRawCoords(300, 880)));
5134
5135 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5136 // display.
5137 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5138 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5139 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5140 WithRawCoords(300, 880)));
5141 secondWindow->consumeMotionEvent(
5142 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5143 secondWindow->assertNoEvents();
5144 firstWindow->assertNoEvents();
5145}
5146
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005147TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5148 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5149
5150 // Send hover enter to second window
5151 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5152 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5153 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5154 WithCoords(100, 80), WithRawCoords(300, 880)));
5155
5156 mDispatcher->cancelCurrentTouch();
5157
5158 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5159 WithRawCoords(300, 880)));
5160 secondWindow->assertNoEvents();
5161 firstWindow->assertNoEvents();
5162}
5163
Prabir Pradhan453ae732023-10-13 14:30:14 +00005164// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005165TEST_F(InputDispatcherDisplayProjectionTest,
5166 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5167 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5168
5169 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5170 ui::Transform secondDisplayTransform;
5171 secondDisplayTransform.set(matrix);
5172 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5173
5174 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5175 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5176 addWindow(secondWindowClone);
5177
5178 // Send hover enter to second window
5179 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5180 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5181 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5182 WithCoords(100, 80), WithRawCoords(300, 880),
5183 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5184
5185 mDispatcher->cancelCurrentTouch();
5186
5187 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5188 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5189 WithRawCoords(300, 880),
5190 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5191 secondWindow->assertNoEvents();
5192 firstWindow->assertNoEvents();
5193}
5194
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005195/** Ensure consistent behavior of InputDispatcher in all orientations. */
5196class InputDispatcherDisplayOrientationFixture
5197 : public InputDispatcherDisplayProjectionTest,
5198 public ::testing::WithParamInterface<ui::Rotation> {};
5199
5200// This test verifies the touchable region of a window for all rotations of the display by tapping
5201// in different locations on the display, specifically points close to the four corners of a
5202// window.
5203TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5204 constexpr static int32_t displayWidth = 400;
5205 constexpr static int32_t displayHeight = 800;
5206
5207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5208
5209 const auto rotation = GetParam();
5210
5211 // Set up the display with the specified rotation.
5212 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5213 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5214 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5215 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5216 logicalDisplayWidth, logicalDisplayHeight);
5217 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5218
5219 // Create a window with its bounds determined in the logical display.
5220 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5221 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5222 sp<FakeWindowHandle> window =
5223 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5224 window->setFrame(frameInDisplay, displayTransform);
5225 addWindow(window);
5226
5227 // The following points in logical display space should be inside the window.
5228 static const std::array<vec2, 4> insidePoints{
5229 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5230 for (const auto pointInsideWindow : insidePoints) {
5231 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5232 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005233 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5234 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5235 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005236 window->consumeMotionDown();
5237
Prabir Pradhan678438e2023-04-13 19:32:51 +00005238 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5239 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5240 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005241 window->consumeMotionUp();
5242 }
5243
5244 // The following points in logical display space should be outside the window.
5245 static const std::array<vec2, 5> outsidePoints{
5246 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5247 for (const auto pointOutsideWindow : outsidePoints) {
5248 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5249 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005250 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5251 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5252 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005253
Prabir Pradhan678438e2023-04-13 19:32:51 +00005254 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5255 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5256 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005257 }
5258 window->assertNoEvents();
5259}
5260
5261// Run the precision tests for all rotations.
5262INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5263 InputDispatcherDisplayOrientationFixture,
5264 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5265 ui::ROTATION_270),
5266 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5267 return ftl::enum_string(testParamInfo.param);
5268 });
5269
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005270using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5271 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005272
5273class TransferTouchFixture : public InputDispatcherTest,
5274 public ::testing::WithParamInterface<TransferFunction> {};
5275
5276TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005278
5279 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005280 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005281 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5282 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005284 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005285 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5286 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005287 sp<FakeWindowHandle> wallpaper =
5288 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5289 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005290 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005291 mDispatcher->onWindowInfosChanged(
5292 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005293
5294 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5296 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005297
Svet Ganov5d3bc372020-01-26 23:11:07 -08005298 // Only the first window should get the down event
5299 firstWindow->consumeMotionDown();
5300 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005301 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005302
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005303 // Transfer touch to the second window
5304 TransferFunction f = GetParam();
5305 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5306 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005307 // The first window gets cancel and the second gets down
5308 firstWindow->consumeMotionCancel();
5309 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005310 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005311
5312 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005313 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5314 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005315 // The first window gets no events and the second gets up
5316 firstWindow->assertNoEvents();
5317 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005318 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005319}
5320
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005321/**
5322 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5323 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5324 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5325 * natural to the user.
5326 * In this test, we are sending a pointer to both spy window and first window. We then try to
5327 * transfer touch to the second window. The dispatcher should identify the first window as the
5328 * one that should lose the gesture, and therefore the action should be to move the gesture from
5329 * the first window to the second.
5330 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5331 * the other API, as well.
5332 */
5333TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5335
5336 // Create a couple of windows + a spy window
5337 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005338 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005339 spyWindow->setTrustedOverlay(true);
5340 spyWindow->setSpy(true);
5341 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005342 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005343 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005344 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005345
5346 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005347 mDispatcher->onWindowInfosChanged(
5348 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005349
5350 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005351 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5352 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005353 // Only the first window and spy should get the down event
5354 spyWindow->consumeMotionDown();
5355 firstWindow->consumeMotionDown();
5356
5357 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5358 // if f === 'transferTouch'.
5359 TransferFunction f = GetParam();
5360 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5361 ASSERT_TRUE(success);
5362 // The first window gets cancel and the second gets down
5363 firstWindow->consumeMotionCancel();
5364 secondWindow->consumeMotionDown();
5365
5366 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5368 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005369 // The first window gets no events and the second+spy get up
5370 firstWindow->assertNoEvents();
5371 spyWindow->consumeMotionUp();
5372 secondWindow->consumeMotionUp();
5373}
5374
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005375TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005377
5378 PointF touchPoint = {10, 10};
5379
5380 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005381 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005382 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5383 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005384 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005385 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005386 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5387 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005388 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005389
5390 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005391 mDispatcher->onWindowInfosChanged(
5392 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005393
5394 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005395 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5396 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5397 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005398 // Only the first window should get the down event
5399 firstWindow->consumeMotionDown();
5400 secondWindow->assertNoEvents();
5401
5402 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005403 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5404 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005405 // Only the first window should get the pointer down event
5406 firstWindow->consumeMotionPointerDown(1);
5407 secondWindow->assertNoEvents();
5408
5409 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005410 TransferFunction f = GetParam();
5411 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5412 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005413 // The first window gets cancel and the second gets down and pointer down
5414 firstWindow->consumeMotionCancel();
5415 secondWindow->consumeMotionDown();
5416 secondWindow->consumeMotionPointerDown(1);
5417
5418 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005419 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5420 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005421 // The first window gets nothing and the second gets pointer up
5422 firstWindow->assertNoEvents();
5423 secondWindow->consumeMotionPointerUp(1);
5424
5425 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005426 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5427 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005428 // The first window gets nothing and the second gets up
5429 firstWindow->assertNoEvents();
5430 secondWindow->consumeMotionUp();
5431}
5432
Arthur Hungc539dbb2022-12-08 07:45:36 +00005433TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5435
5436 // Create a couple of windows
5437 sp<FakeWindowHandle> firstWindow =
5438 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5439 ADISPLAY_ID_DEFAULT);
5440 firstWindow->setDupTouchToWallpaper(true);
5441 sp<FakeWindowHandle> secondWindow =
5442 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5443 ADISPLAY_ID_DEFAULT);
5444 secondWindow->setDupTouchToWallpaper(true);
5445
5446 sp<FakeWindowHandle> wallpaper1 =
5447 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5448 wallpaper1->setIsWallpaper(true);
5449
5450 sp<FakeWindowHandle> wallpaper2 =
5451 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5452 wallpaper2->setIsWallpaper(true);
5453 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005454 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5455 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5456 {},
5457 0,
5458 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005459
5460 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005461 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5462 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005463
5464 // Only the first window should get the down event
5465 firstWindow->consumeMotionDown();
5466 secondWindow->assertNoEvents();
5467 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5468 wallpaper2->assertNoEvents();
5469
5470 // Transfer touch focus to the second window
5471 TransferFunction f = GetParam();
5472 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5473 ASSERT_TRUE(success);
5474
5475 // The first window gets cancel and the second gets down
5476 firstWindow->consumeMotionCancel();
5477 secondWindow->consumeMotionDown();
5478 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5479 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5480
5481 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005482 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5483 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005484 // The first window gets no events and the second gets up
5485 firstWindow->assertNoEvents();
5486 secondWindow->consumeMotionUp();
5487 wallpaper1->assertNoEvents();
5488 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5489}
5490
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005491// For the cases of single pointer touch and two pointers non-split touch, the api's
5492// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5493// for the case where there are multiple pointers split across several windows.
5494INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5495 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005496 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5497 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005498 return dispatcher->transferTouch(destChannelToken,
5499 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005500 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005501 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5502 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005503 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005504 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005505 }));
5506
Svet Ganov5d3bc372020-01-26 23:11:07 -08005507TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005509
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005510 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005511 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5512 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005513 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005514
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005515 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005516 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5517 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005518 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005519
5520 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005521 mDispatcher->onWindowInfosChanged(
5522 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005523
5524 PointF pointInFirst = {300, 200};
5525 PointF pointInSecond = {300, 600};
5526
5527 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5530 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005531 // Only the first window should get the down event
5532 firstWindow->consumeMotionDown();
5533 secondWindow->assertNoEvents();
5534
5535 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005536 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5537 ADISPLAY_ID_DEFAULT,
5538 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005539 // The first window gets a move and the second a down
5540 firstWindow->consumeMotionMove();
5541 secondWindow->consumeMotionDown();
5542
5543 // Transfer touch focus to the second window
5544 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5545 // The first window gets cancel and the new gets pointer down (it already saw down)
5546 firstWindow->consumeMotionCancel();
5547 secondWindow->consumeMotionPointerDown(1);
5548
5549 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005550 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5551 ADISPLAY_ID_DEFAULT,
5552 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005553 // The first window gets nothing and the second gets pointer up
5554 firstWindow->assertNoEvents();
5555 secondWindow->consumeMotionPointerUp(1);
5556
5557 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005558 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5559 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005560 // The first window gets nothing and the second gets up
5561 firstWindow->assertNoEvents();
5562 secondWindow->consumeMotionUp();
5563}
5564
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005565// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5566// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5567// touch is not supported, so the touch should continue on those windows and the transferred-to
5568// window should get nothing.
5569TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5571
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005572 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005573 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5574 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005575 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005576
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005577 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005578 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5579 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005580 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005581
5582 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005583 mDispatcher->onWindowInfosChanged(
5584 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005585
5586 PointF pointInFirst = {300, 200};
5587 PointF pointInSecond = {300, 600};
5588
5589 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005590 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5591 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5592 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005593 // Only the first window should get the down event
5594 firstWindow->consumeMotionDown();
5595 secondWindow->assertNoEvents();
5596
5597 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005598 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5599 ADISPLAY_ID_DEFAULT,
5600 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005601 // The first window gets a move and the second a down
5602 firstWindow->consumeMotionMove();
5603 secondWindow->consumeMotionDown();
5604
5605 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005606 const bool transferred =
5607 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005608 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5609 ASSERT_FALSE(transferred);
5610 firstWindow->assertNoEvents();
5611 secondWindow->assertNoEvents();
5612
5613 // The rest of the dispatch should proceed as normal
5614 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005615 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5616 ADISPLAY_ID_DEFAULT,
5617 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005618 // The first window gets MOVE and the second gets pointer up
5619 firstWindow->consumeMotionMove();
5620 secondWindow->consumeMotionUp();
5621
5622 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005623 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5624 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005625 // The first window gets nothing and the second gets up
5626 firstWindow->consumeMotionUp();
5627 secondWindow->assertNoEvents();
5628}
5629
Arthur Hungabbb9d82021-09-01 14:52:30 +00005630// This case will create two windows and one mirrored window on the default display and mirror
5631// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5632// the windows info of second display before default display.
5633TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5635 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005636 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005637 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005638 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005639 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005640 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005641
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005642 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005643 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005644
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005645 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005646 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005647
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005648 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005649 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005650
5651 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005652 mDispatcher->onWindowInfosChanged(
5653 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5654 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5655 *secondWindowInPrimary->getInfo()},
5656 {},
5657 0,
5658 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005659
5660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005661 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005662 {50, 50}))
5663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5664
5665 // Window should receive motion event.
5666 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5667
5668 // Transfer touch focus
5669 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5670 secondWindowInPrimary->getToken()));
5671 // The first window gets cancel.
5672 firstWindowInPrimary->consumeMotionCancel();
5673 secondWindowInPrimary->consumeMotionDown();
5674
5675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005676 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005677 ADISPLAY_ID_DEFAULT, {150, 50}))
5678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5679 firstWindowInPrimary->assertNoEvents();
5680 secondWindowInPrimary->consumeMotionMove();
5681
5682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005683 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684 {150, 50}))
5685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5686 firstWindowInPrimary->assertNoEvents();
5687 secondWindowInPrimary->consumeMotionUp();
5688}
5689
5690// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5691// 'transferTouch' api.
5692TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5694 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005695 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005696 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005697 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005698 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005699 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005701 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005702 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005703
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005704 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005706
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005707 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005708 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005709
5710 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005711 mDispatcher->onWindowInfosChanged(
5712 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5713 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5714 *secondWindowInPrimary->getInfo()},
5715 {},
5716 0,
5717 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005718
5719 // Touch on second display.
5720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5722 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5724
5725 // Window should receive motion event.
5726 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5727
5728 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005729 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005730
5731 // The first window gets cancel.
5732 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5733 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5734
5735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005736 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005737 SECOND_DISPLAY_ID, {150, 50}))
5738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5739 firstWindowInPrimary->assertNoEvents();
5740 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5741
5742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005743 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5745 firstWindowInPrimary->assertNoEvents();
5746 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5747}
5748
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005749TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005751 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5752 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005753
Vishnu Nair47074b82020-08-14 11:54:47 -07005754 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005756 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005757
5758 window->consumeFocusEvent(true);
5759
Prabir Pradhan678438e2023-04-13 19:32:51 +00005760 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005761
5762 // Window should receive key down event.
5763 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005764
5765 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005766 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005767 mFakePolicy->assertUserActivityPoked();
5768}
5769
5770TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5772 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5773 "Fake Window", ADISPLAY_ID_DEFAULT);
5774
5775 window->setDisableUserActivity(true);
5776 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005777 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005778 setFocusedWindow(window);
5779
5780 window->consumeFocusEvent(true);
5781
5782 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5783
5784 // Window should receive key down event.
5785 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5786
5787 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005788 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005789 mFakePolicy->assertUserActivityNotPoked();
5790}
5791
5792TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5794 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5795 "Fake Window", ADISPLAY_ID_DEFAULT);
5796
5797 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005799 setFocusedWindow(window);
5800
5801 window->consumeFocusEvent(true);
5802
5803 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5804 mDispatcher->waitForIdle();
5805
5806 // System key is not passed down
5807 window->assertNoEvents();
5808
5809 // Should have poked user activity
5810 mFakePolicy->assertUserActivityPoked();
5811}
5812
5813TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5815 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5816 "Fake Window", ADISPLAY_ID_DEFAULT);
5817
5818 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005819 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005820 setFocusedWindow(window);
5821
5822 window->consumeFocusEvent(true);
5823
5824 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5825 mDispatcher->waitForIdle();
5826
5827 // System key is not passed down
5828 window->assertNoEvents();
5829
5830 // Should have poked user activity
5831 mFakePolicy->assertUserActivityPoked();
5832}
5833
5834TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5836 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5837 "Fake Window", ADISPLAY_ID_DEFAULT);
5838
5839 window->setDisableUserActivity(true);
5840 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005841 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005842 setFocusedWindow(window);
5843
5844 window->consumeFocusEvent(true);
5845
5846 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5847 mDispatcher->waitForIdle();
5848
5849 // System key is not passed down
5850 window->assertNoEvents();
5851
5852 // Should have poked user activity
5853 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005854}
5855
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005856TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5858 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5859 "Fake Window", ADISPLAY_ID_DEFAULT);
5860
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005861 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005862
5863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005864 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005865 ADISPLAY_ID_DEFAULT, {100, 100}))
5866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5867
5868 window->consumeMotionEvent(
5869 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5870
5871 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005872 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005873 mFakePolicy->assertUserActivityPoked();
5874}
5875
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005876TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005878 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5879 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005880
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005882
Prabir Pradhan678438e2023-04-13 19:32:51 +00005883 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005884 mDispatcher->waitForIdle();
5885
5886 window->assertNoEvents();
5887}
5888
5889// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5890TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005892 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5893 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005894
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005895 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005896
5897 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005898 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005899 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005900 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5901 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005902
5903 // Window should receive only the motion event
5904 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5905 window->assertNoEvents(); // Key event or focus event will not be received
5906}
5907
arthurhungea3f4fc2020-12-21 23:18:53 +08005908TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5910
arthurhungea3f4fc2020-12-21 23:18:53 +08005911 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005912 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5913 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005914 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005915
arthurhungea3f4fc2020-12-21 23:18:53 +08005916 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005917 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5918 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005919 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005920
5921 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005922 mDispatcher->onWindowInfosChanged(
5923 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005924
5925 PointF pointInFirst = {300, 200};
5926 PointF pointInSecond = {300, 600};
5927
5928 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005929 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5930 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5931 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005932 // Only the first window should get the down event
5933 firstWindow->consumeMotionDown();
5934 secondWindow->assertNoEvents();
5935
5936 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005937 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5938 ADISPLAY_ID_DEFAULT,
5939 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005940 // The first window gets a move and the second a down
5941 firstWindow->consumeMotionMove();
5942 secondWindow->consumeMotionDown();
5943
5944 // Send pointer cancel to the second window
5945 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005946 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005947 {pointInFirst, pointInSecond});
5948 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005949 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005950 // The first window gets move and the second gets cancel.
5951 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5952 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5953
5954 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005955 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5956 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005957 // The first window gets up and the second gets nothing.
5958 firstWindow->consumeMotionUp();
5959 secondWindow->assertNoEvents();
5960}
5961
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005962TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5964
5965 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005966 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005968 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5969 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5970 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5971
Harry Cutts33476232023-01-30 19:57:29 +00005972 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005973 window->assertNoEvents();
5974 mDispatcher->waitForIdle();
5975}
5976
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005977using InputDispatcherMonitorTest = InputDispatcherTest;
5978
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005979/**
5980 * Two entities that receive touch: A window, and a global monitor.
5981 * The touch goes to the window, and then the window disappears.
5982 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5983 * for the monitor, as well.
5984 * 1. foregroundWindow
5985 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5986 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005987TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5989 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005990 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005991
Prabir Pradhanfb549072023-10-05 19:17:36 +00005992 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005993
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005994 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005996 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005997 {100, 200}))
5998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5999
6000 // Both the foreground window and the global monitor should receive the touch down
6001 window->consumeMotionDown();
6002 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6003
6004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006005 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006006 ADISPLAY_ID_DEFAULT, {110, 200}))
6007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6008
6009 window->consumeMotionMove();
6010 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6011
6012 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006013 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006014 window->consumeMotionCancel();
6015 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6016
6017 // If more events come in, there will be no more foreground window to send them to. This will
6018 // cause a cancel for the monitor, as well.
6019 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006020 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006021 ADISPLAY_ID_DEFAULT, {120, 200}))
6022 << "Injection should fail because the window was removed";
6023 window->assertNoEvents();
6024 // Global monitor now gets the cancel
6025 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6026}
6027
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006028TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006029 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006030 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6031 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006032 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006033
Prabir Pradhanfb549072023-10-05 19:17:36 +00006034 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006035
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006037 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006039 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006040 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006041}
6042
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006043TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006044 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006045
Chris Yea209fde2020-07-22 13:54:51 -07006046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006047 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6048 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006049 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006050
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006052 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006054 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006055 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006056
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006057 // Pilfer pointers from the monitor.
6058 // This should not do anything and the window should continue to receive events.
6059 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006060
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006062 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006063 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006065
6066 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6067 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006068}
6069
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006070TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006072 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6073 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006074 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006075 window->setWindowOffset(20, 40);
6076 window->setWindowTransform(0, 1, -1, 0);
6077
Prabir Pradhanfb549072023-10-05 19:17:36 +00006078 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006079
6080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006081 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6083 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6084 MotionEvent* event = monitor.consumeMotion();
6085 // Even though window has transform, gesture monitor must not.
6086 ASSERT_EQ(ui::Transform(), event->getTransform());
6087}
6088
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006089TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006091 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006092
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006093 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006094 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006095 << "Injection should fail if there is a monitor, but no touchable window";
6096 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006097}
6098
chaviw81e2bb92019-12-18 15:03:51 -08006099TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006101 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6102 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006104 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006105
6106 NotifyMotionArgs motionArgs =
6107 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6108 ADISPLAY_ID_DEFAULT);
6109
Prabir Pradhan678438e2023-04-13 19:32:51 +00006110 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006111 // Window should receive motion down event.
6112 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6113
6114 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006115 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006116 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6117 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6118 motionArgs.pointerCoords[0].getX() - 10);
6119
Prabir Pradhan678438e2023-04-13 19:32:51 +00006120 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006121 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006122}
6123
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006124/**
6125 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6126 * the device default right away. In the test scenario, we check both the default value,
6127 * and the action of enabling / disabling.
6128 */
6129TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006131 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6132 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006133 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006134
6135 // Set focused application.
6136 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006137 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006138
6139 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006140 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006141 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006142 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006143
6144 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006145 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006147 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006148
6149 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006150 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006151 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006152 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006153 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006154 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006155 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006156 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006157
6158 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006159 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006160 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006161 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006162
6163 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006164 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006165 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006166 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006167 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006168 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006169 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006170 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006171
6172 window->assertNoEvents();
6173}
6174
Gang Wange9087892020-01-07 12:17:14 -05006175TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006177 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6178 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006179
6180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006181 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006184 setFocusedWindow(window);
6185
Harry Cutts33476232023-01-30 19:57:29 +00006186 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006187
Prabir Pradhan678438e2023-04-13 19:32:51 +00006188 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6189 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006190
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006191 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006192
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006193 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006194 ASSERT_NE(verified, nullptr);
6195 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6196
6197 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6198 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6199 ASSERT_EQ(keyArgs.source, verified->source);
6200 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6201
6202 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6203
6204 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006205 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006206 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006207 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6208 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6209 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6210 ASSERT_EQ(0, verifiedKey.repeatCount);
6211}
6212
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006213TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006215 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6216 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006217
6218 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6219
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006220 ui::Transform transform;
6221 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6222
6223 gui::DisplayInfo displayInfo;
6224 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6225 displayInfo.transform = transform;
6226
Patrick Williamsd828f302023-04-28 17:52:08 -05006227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006228
Prabir Pradhan678438e2023-04-13 19:32:51 +00006229 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006230 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6231 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006232 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006233
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006234 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006235
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006236 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006237 ASSERT_NE(verified, nullptr);
6238 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6239
6240 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6241 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6242 EXPECT_EQ(motionArgs.source, verified->source);
6243 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6244
6245 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6246
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006247 const vec2 rawXY =
6248 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6249 motionArgs.pointerCoords[0].getXYValue());
6250 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6251 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006252 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006253 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006254 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006255 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6256 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6257}
6258
chaviw09c8d2d2020-08-24 15:48:26 -07006259/**
6260 * Ensure that separate calls to sign the same data are generating the same key.
6261 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6262 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6263 * tests.
6264 */
6265TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6266 KeyEvent event = getTestKeyEvent();
6267 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6268
6269 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6270 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6271 ASSERT_EQ(hmac1, hmac2);
6272}
6273
6274/**
6275 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6276 */
6277TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6278 KeyEvent event = getTestKeyEvent();
6279 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6280 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6281
6282 verifiedEvent.deviceId += 1;
6283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6284
6285 verifiedEvent.source += 1;
6286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6287
6288 verifiedEvent.eventTimeNanos += 1;
6289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6290
6291 verifiedEvent.displayId += 1;
6292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6293
6294 verifiedEvent.action += 1;
6295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6296
6297 verifiedEvent.downTimeNanos += 1;
6298 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6299
6300 verifiedEvent.flags += 1;
6301 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6302
6303 verifiedEvent.keyCode += 1;
6304 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6305
6306 verifiedEvent.scanCode += 1;
6307 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6308
6309 verifiedEvent.metaState += 1;
6310 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6311
6312 verifiedEvent.repeatCount += 1;
6313 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6314}
6315
Vishnu Nair958da932020-08-21 17:12:37 -07006316TEST_F(InputDispatcherTest, SetFocusedWindow) {
6317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6318 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006319 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006320 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006322 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6323
6324 // Top window is also focusable but is not granted focus.
6325 windowTop->setFocusable(true);
6326 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006327 mDispatcher->onWindowInfosChanged(
6328 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006329 setFocusedWindow(windowSecond);
6330
6331 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006333 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006334
6335 // Focused window should receive event.
6336 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6337 windowTop->assertNoEvents();
6338}
6339
6340TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6341 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6342 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006343 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006344 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6345
6346 window->setFocusable(true);
6347 // Release channel for window is no longer valid.
6348 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006349 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006350 setFocusedWindow(window);
6351
6352 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006353 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006354
6355 // window channel is invalid, so it should not receive any input event.
6356 window->assertNoEvents();
6357}
6358
6359TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6361 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006362 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006363 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6365
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006366 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006367 setFocusedWindow(window);
6368
6369 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006370 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006371
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006372 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006373 window->assertNoEvents();
6374}
6375
6376TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6377 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6378 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006379 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006380 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006381 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006382 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6383
6384 windowTop->setFocusable(true);
6385 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006386 mDispatcher->onWindowInfosChanged(
6387 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006388 setFocusedWindow(windowTop);
6389 windowTop->consumeFocusEvent(true);
6390
Chavi Weingarten847e8512023-03-29 00:26:09 +00006391 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006392 mDispatcher->onWindowInfosChanged(
6393 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006394 windowSecond->consumeFocusEvent(true);
6395 windowTop->consumeFocusEvent(false);
6396
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006398 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006399
6400 // Focused window should receive event.
6401 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6402}
6403
Chavi Weingarten847e8512023-03-29 00:26:09 +00006404TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6406 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006407 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006408 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006409 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006410 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6411
6412 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006413 windowSecond->setFocusable(false);
6414 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006415 mDispatcher->onWindowInfosChanged(
6416 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006417 setFocusedWindow(windowTop);
6418 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006419
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006421 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006422
6423 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006424 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006425 windowSecond->assertNoEvents();
6426}
6427
6428TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6430 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006431 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006432 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006433 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6434 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006435 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6436
6437 window->setFocusable(true);
6438 previousFocusedWindow->setFocusable(true);
6439 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006440 mDispatcher->onWindowInfosChanged(
6441 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006442 setFocusedWindow(previousFocusedWindow);
6443 previousFocusedWindow->consumeFocusEvent(true);
6444
6445 // Requesting focus on invisible window takes focus from currently focused window.
6446 setFocusedWindow(window);
6447 previousFocusedWindow->consumeFocusEvent(false);
6448
6449 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006451 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6452 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006453
6454 // Window does not get focus event or key down.
6455 window->assertNoEvents();
6456
6457 // Window becomes visible.
6458 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006460
6461 // Window receives focus event.
6462 window->consumeFocusEvent(true);
6463 // Focused window receives key down.
6464 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6465}
6466
Vishnu Nair599f1412021-06-21 10:39:58 -07006467TEST_F(InputDispatcherTest, DisplayRemoved) {
6468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6469 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006470 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006471 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6472
6473 // window is granted focus.
6474 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006476 setFocusedWindow(window);
6477 window->consumeFocusEvent(true);
6478
6479 // When a display is removed window loses focus.
6480 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6481 window->consumeFocusEvent(false);
6482}
6483
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006484/**
6485 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6486 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6487 * of the 'slipperyEnterWindow'.
6488 *
6489 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6490 * a way so that the touched location is no longer covered by the top window.
6491 *
6492 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6493 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6494 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6495 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6496 * with ACTION_DOWN).
6497 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6498 * window moved itself away from the touched location and had Flag::SLIPPERY.
6499 *
6500 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6501 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6502 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6503 *
6504 * In this test, we ensure that the event received by the bottom window has
6505 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6506 */
6507TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006508 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006509 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006510
6511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6512 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6513
6514 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006515 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006516 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006517 // Make sure this one overlaps the bottom window
6518 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6519 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6520 // one. Windows with the same owner are not considered to be occluding each other.
6521 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6522
6523 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006524 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006525 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6526
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006527 mDispatcher->onWindowInfosChanged(
6528 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006529
6530 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006531 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6532 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6533 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006534 slipperyExitWindow->consumeMotionDown();
6535 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006536 mDispatcher->onWindowInfosChanged(
6537 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006538
Prabir Pradhan678438e2023-04-13 19:32:51 +00006539 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6540 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6541 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006542
6543 slipperyExitWindow->consumeMotionCancel();
6544
6545 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6546 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6547}
6548
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006549/**
6550 * Two windows, one on the left and another on the right. The left window is slippery. The right
6551 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6552 * touch moves from the left window into the right window, the gesture should continue to go to the
6553 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6554 * reproduces a crash.
6555 */
6556TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6558
6559 sp<FakeWindowHandle> leftSlipperyWindow =
6560 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6561 leftSlipperyWindow->setSlippery(true);
6562 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6563
6564 sp<FakeWindowHandle> rightDropTouchesWindow =
6565 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6566 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6567 rightDropTouchesWindow->setDropInput(true);
6568
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006569 mDispatcher->onWindowInfosChanged(
6570 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006571
6572 // Start touch in the left window
6573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6574 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6575 .build());
6576 leftSlipperyWindow->consumeMotionDown();
6577
6578 // And move it into the right window
6579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6580 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6581 .build());
6582
6583 // Since the right window isn't eligible to receive input, touch does not slip.
6584 // The left window continues to receive the gesture.
6585 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6586 rightDropTouchesWindow->assertNoEvents();
6587}
6588
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006589/**
6590 * A single window is on screen first. Touch is injected into that window. Next, a second window
6591 * appears. Since the first window is slippery, touch will move from the first window to the second.
6592 */
6593TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6595 sp<FakeWindowHandle> originalWindow =
6596 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6597 originalWindow->setFrame(Rect(0, 0, 200, 200));
6598 originalWindow->setSlippery(true);
6599
6600 sp<FakeWindowHandle> appearingWindow =
6601 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6602 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6603
6604 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6605
6606 // Touch down on the original window
6607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6608 injectMotionEvent(*mDispatcher,
6609 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6610 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6611 .build()));
6612 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6613
6614 // Now, a new window appears. This could be, for example, a notification shade that appears
6615 // after user starts to drag down on the launcher window.
6616 mDispatcher->onWindowInfosChanged(
6617 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6619 injectMotionEvent(*mDispatcher,
6620 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6621 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6622 .build()));
6623 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6624 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6626 injectMotionEvent(*mDispatcher,
6627 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6628 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6629 .build()));
6630 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6631
6632 originalWindow->assertNoEvents();
6633 appearingWindow->assertNoEvents();
6634}
6635
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006636TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006637 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6639
6640 sp<FakeWindowHandle> leftWindow =
6641 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6642 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006643 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006644
6645 sp<FakeWindowHandle> rightSpy =
6646 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6647 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006648 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006649 rightSpy->setSpy(true);
6650 rightSpy->setTrustedOverlay(true);
6651
6652 sp<FakeWindowHandle> rightWindow =
6653 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6654 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006655 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006656
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006657 mDispatcher->onWindowInfosChanged(
6658 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006659
6660 // Touch in the left window
6661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6662 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6663 .build());
6664 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6665 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006666 ASSERT_NO_FATAL_FAILURE(
6667 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006668
6669 // Touch another finger over the right windows
6670 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6671 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6672 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6673 .build());
6674 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6675 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6676 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6677 mDispatcher->waitForIdle();
6678 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006679 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6680 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006681
6682 // Release finger over left window. The UP actions are not treated as device interaction.
6683 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6684 // is part of the UP action, we do not treat this as device interaction.
6685 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6686 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6687 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6688 .build());
6689 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6690 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6691 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6692 mDispatcher->waitForIdle();
6693 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6694
6695 // Move remaining finger
6696 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6697 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6698 .build());
6699 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6700 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6701 mDispatcher->waitForIdle();
6702 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006703 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006704
6705 // Release all fingers
6706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6707 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6708 .build());
6709 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6710 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6711 mDispatcher->waitForIdle();
6712 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6713}
6714
6715TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6717
6718 sp<FakeWindowHandle> window =
6719 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6720 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006721 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006722
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006723 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006724 setFocusedWindow(window);
6725 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6726
6727 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6728 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6729 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006730 ASSERT_NO_FATAL_FAILURE(
6731 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006732
6733 // The UP actions are not treated as device interaction.
6734 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6735 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6736 mDispatcher->waitForIdle();
6737 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6738}
6739
Prabir Pradhan5893d362023-11-17 04:30:40 +00006740TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6742
6743 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6744 ADISPLAY_ID_DEFAULT);
6745 left->setFrame(Rect(0, 0, 100, 100));
6746 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6747 "Right Window", ADISPLAY_ID_DEFAULT);
6748 right->setFrame(Rect(100, 0, 200, 100));
6749 sp<FakeWindowHandle> spy =
6750 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6751 spy->setFrame(Rect(0, 0, 200, 100));
6752 spy->setTrustedOverlay(true);
6753 spy->setSpy(true);
6754
6755 mDispatcher->onWindowInfosChanged(
6756 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6757
6758 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6759 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6760 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6761 mDispatcher->notifyMotion(notifyArgs);
6762
6763 const MotionEvent& leftEnter = left->consumeMotionEvent(
6764 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6765 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6766
6767 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6768 Not(WithEventId(notifyArgs.id)),
6769 Not(WithEventId(leftEnter.getId())),
6770 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6771
6772 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6773 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6774 {PointF{150, 50}});
6775 mDispatcher->notifyMotion(notifyArgs);
6776
6777 const MotionEvent& leftExit = left->consumeMotionEvent(
6778 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6779 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6780
6781 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6782 Not(WithEventId(notifyArgs.id)),
6783 Not(WithEventId(leftExit.getId())),
6784 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6785
6786 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6787}
6788
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006789class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6790protected:
6791 std::shared_ptr<FakeApplicationHandle> mApp;
6792 sp<FakeWindowHandle> mWindow;
6793
6794 virtual void SetUp() override {
6795 InputDispatcherTest::SetUp();
6796
6797 mApp = std::make_shared<FakeApplicationHandle>();
6798
6799 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6800 mWindow->setFrame(Rect(0, 0, 100, 100));
6801
6802 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6803 setFocusedWindow(mWindow);
6804 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6805 }
6806
6807 void setFallback(int32_t keycode) {
6808 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6809 return KeyEventBuilder(event).keyCode(keycode).build();
6810 });
6811 }
6812
6813 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006814 const KeyEvent& event = mWindow->consumeKey(handled);
6815 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006816 }
6817};
6818
6819TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6820 mDispatcher->notifyKey(
6821 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6822 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6823 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6824}
6825
6826TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6827 mDispatcher->notifyKey(
6828 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6829 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6830 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6831}
6832
6833TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6834 mDispatcher->notifyKey(
6835 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6836
6837 // Do not handle this key event.
6838 consumeKey(/*handled=*/false,
6839 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6840 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6841
6842 // Since the policy did not request any fallback to be generated, ensure there are no events.
6843 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6844}
6845
6846TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6847 setFallback(AKEYCODE_B);
6848 mDispatcher->notifyKey(
6849 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6850
6851 // Do not handle this key event.
6852 consumeKey(/*handled=*/false,
6853 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6854
6855 // Since the key was not handled, ensure the fallback event was dispatched instead.
6856 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6857 consumeKey(/*handled=*/true,
6858 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6859 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6860
6861 // Release the original key, and ensure the fallback key is also released.
6862 mDispatcher->notifyKey(
6863 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6864 consumeKey(/*handled=*/false,
6865 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6866 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6867 consumeKey(/*handled=*/true,
6868 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6869 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6870
6871 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6872 mWindow->assertNoEvents();
6873}
6874
6875TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6876 setFallback(AKEYCODE_B);
6877 mDispatcher->notifyKey(
6878 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6879
6880 // Do not handle this key event, but handle the fallback.
6881 consumeKey(/*handled=*/false,
6882 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6883 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6884 consumeKey(/*handled=*/true,
6885 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6886 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6887
6888 // Release the original key, and ensure the fallback key is also released.
6889 mDispatcher->notifyKey(
6890 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6891 // But this time, the app handles the original key.
6892 consumeKey(/*handled=*/true,
6893 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6894 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6895 // Ensure the fallback key is canceled.
6896 consumeKey(/*handled=*/true,
6897 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6898 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6899
6900 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6901 mWindow->assertNoEvents();
6902}
6903
6904TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6905 setFallback(AKEYCODE_B);
6906 mDispatcher->notifyKey(
6907 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6908
6909 // Do not handle this key event.
6910 consumeKey(/*handled=*/false,
6911 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6913 // App does not handle the fallback either, so ensure another fallback is not generated.
6914 setFallback(AKEYCODE_C);
6915 consumeKey(/*handled=*/false,
6916 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6917 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6918
6919 // Release the original key, and ensure the fallback key is also released.
6920 setFallback(AKEYCODE_B);
6921 mDispatcher->notifyKey(
6922 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6923 consumeKey(/*handled=*/false,
6924 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6925 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6926 consumeKey(/*handled=*/false,
6927 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6928 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6929
6930 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6931 mWindow->assertNoEvents();
6932}
6933
6934TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6935 setFallback(AKEYCODE_B);
6936 mDispatcher->notifyKey(
6937 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6938
6939 // Do not handle this key event, so fallback is generated.
6940 consumeKey(/*handled=*/false,
6941 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6942 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6943 consumeKey(/*handled=*/true,
6944 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6945 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6946
6947 // Release the original key, but assume the policy is misbehaving and it
6948 // generates an inconsistent fallback to the one from the DOWN event.
6949 setFallback(AKEYCODE_C);
6950 mDispatcher->notifyKey(
6951 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6952 consumeKey(/*handled=*/false,
6953 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6955 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6956 consumeKey(/*handled=*/true,
6957 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6958 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6959
6960 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6961 mWindow->assertNoEvents();
6962}
6963
6964TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6965 setFallback(AKEYCODE_B);
6966 mDispatcher->notifyKey(
6967 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6968
6969 // Do not handle this key event, so fallback is generated.
6970 consumeKey(/*handled=*/false,
6971 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6972 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6973 consumeKey(/*handled=*/true,
6974 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6975 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6976
6977 // The original key is canceled.
6978 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6979 .keyCode(AKEYCODE_A)
6980 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6981 .build());
6982 consumeKey(/*handled=*/false,
6983 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6984 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6985 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6986 // Ensure the fallback key is also canceled due to the original key being canceled.
6987 consumeKey(/*handled=*/true,
6988 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6989 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6990
6991 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6992 mWindow->assertNoEvents();
6993}
6994
Garfield Tan1c7bc862020-01-28 13:24:04 -08006995class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6996protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006997 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6998 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006999
Chris Yea209fde2020-07-22 13:54:51 -07007000 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007001 sp<FakeWindowHandle> mWindow;
7002
7003 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00007004 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00007005 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00007006 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09007007 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007008 ASSERT_EQ(OK, mDispatcher->start());
7009
7010 setUpWindow();
7011 }
7012
7013 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007014 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007015 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007016
Vishnu Nair47074b82020-08-14 11:54:47 -07007017 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007018 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007019 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007020 mWindow->consumeFocusEvent(true);
7021 }
7022
Chris Ye2ad95392020-09-01 13:44:44 -07007023 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007024 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007025 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007026 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007027 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007028
7029 // Window should receive key down event.
7030 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7031 }
7032
7033 void expectKeyRepeatOnce(int32_t repeatCount) {
7034 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007035 mWindow->consumeKeyEvent(
7036 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007037 }
7038
Chris Ye2ad95392020-09-01 13:44:44 -07007039 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007040 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007041 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007042 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007043 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007044
7045 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007046 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007047 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007048 }
7049};
7050
7051TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007052 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007053 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7054 expectKeyRepeatOnce(repeatCount);
7055 }
7056}
7057
7058TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007059 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007060 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7061 expectKeyRepeatOnce(repeatCount);
7062 }
Harry Cutts33476232023-01-30 19:57:29 +00007063 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007064 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007065 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7066 expectKeyRepeatOnce(repeatCount);
7067 }
7068}
7069
7070TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007071 sendAndConsumeKeyDown(/*deviceId=*/1);
7072 expectKeyRepeatOnce(/*repeatCount=*/1);
7073 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007074 mWindow->assertNoEvents();
7075}
7076
7077TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007078 sendAndConsumeKeyDown(/*deviceId=*/1);
7079 expectKeyRepeatOnce(/*repeatCount=*/1);
7080 sendAndConsumeKeyDown(/*deviceId=*/2);
7081 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007082 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007083 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007084 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007085 expectKeyRepeatOnce(/*repeatCount=*/2);
7086 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007087 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007088 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007089 mWindow->assertNoEvents();
7090}
7091
7092TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
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 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007098 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007099 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007100 mWindow->assertNoEvents();
7101}
7102
liushenxiang42232912021-05-21 20:24:09 +08007103TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7104 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007105 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007106 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007107 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7108 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7109 mWindow->assertNoEvents();
7110}
7111
Garfield Tan1c7bc862020-01-28 13:24:04 -08007112TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007113 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007114 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007115 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007116 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007117 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007118 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007119 }
7120}
7121
7122TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007123 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007124 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007125
7126 std::unordered_set<int32_t> idSet;
7127 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007128 const KeyEvent& repeatEvent = mWindow->consumeKey();
7129 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007130 EXPECT_EQ(idSet.end(), idSet.find(id));
7131 idSet.insert(id);
7132 }
7133}
7134
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007135/* Test InputDispatcher for MultiDisplay */
7136class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7137public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007138 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007139 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007140
Chris Yea209fde2020-07-22 13:54:51 -07007141 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007142 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007143 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007144
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007145 // Set focus window for primary display, but focused display would be second one.
7146 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007147 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007148 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7149
Vishnu Nair958da932020-08-21 17:12:37 -07007150 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007151 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007152
Chris Yea209fde2020-07-22 13:54:51 -07007153 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007154 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007155 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007156 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007157 // Set focus display to second one.
7158 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7159 // Set focus window for second display.
7160 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007161 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007162 mDispatcher->onWindowInfosChanged(
7163 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007164 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007165 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007166 }
7167
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007168 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007169 InputDispatcherTest::TearDown();
7170
Chris Yea209fde2020-07-22 13:54:51 -07007171 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007172 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007173 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007174 windowInSecondary.clear();
7175 }
7176
7177protected:
Chris Yea209fde2020-07-22 13:54:51 -07007178 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007179 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007180 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007181 sp<FakeWindowHandle> windowInSecondary;
7182};
7183
7184TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7185 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007187 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007189 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007190 windowInSecondary->assertNoEvents();
7191
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007192 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007194 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007196 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007197 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007198}
7199
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007200TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007201 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007203 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007204 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007205 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007206 windowInSecondary->assertNoEvents();
7207
7208 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007210 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007211 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007212 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007213
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007214 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007215 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007216
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007217 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007218 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007219
7220 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007221 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007222 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007223 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007224 windowInSecondary->assertNoEvents();
7225}
7226
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007227// Test per-display input monitors for motion event.
7228TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007229 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007230 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007231 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007232 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007233
7234 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007238 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007239 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007240 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007241 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007242
7243 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007245 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007247 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007248 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007249 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007250 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007251
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007252 // Lift up the touch from the second display
7253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007254 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7256 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7257 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7258
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007259 // Test inject a non-pointer motion event.
7260 // If specific a display, it will dispatch to the focused window of particular display,
7261 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007265 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007266 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007267 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007268 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007269}
7270
7271// Test per-display input monitors for key event.
7272TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007273 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007274 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007275 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007276 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007277 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007278
7279 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007281 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007282 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007283 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007284 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007285 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007286}
7287
Vishnu Nair958da932020-08-21 17:12:37 -07007288TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7289 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007290 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007291 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007292 mDispatcher->onWindowInfosChanged(
7293 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7294 *windowInSecondary->getInfo()},
7295 {},
7296 0,
7297 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007298 setFocusedWindow(secondWindowInPrimary);
7299 windowInPrimary->consumeFocusEvent(false);
7300 secondWindowInPrimary->consumeFocusEvent(true);
7301
7302 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7304 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007305 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007306 windowInPrimary->assertNoEvents();
7307 windowInSecondary->assertNoEvents();
7308 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7309}
7310
Arthur Hungdfd528e2021-12-08 13:23:04 +00007311TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7312 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007313 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007314 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007315 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007316
7317 // Test touch down on primary display.
7318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007319 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7321 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7322 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7323
7324 // Test touch down on second display.
7325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007326 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7328 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7329 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7330
7331 // Trigger cancel touch.
7332 mDispatcher->cancelCurrentTouch();
7333 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7334 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7335 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7336 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7337
7338 // Test inject a move motion event, no window/monitor should receive the event.
7339 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007340 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007341 ADISPLAY_ID_DEFAULT, {110, 200}))
7342 << "Inject motion event should return InputEventInjectionResult::FAILED";
7343 windowInPrimary->assertNoEvents();
7344 monitorInPrimary.assertNoEvents();
7345
7346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007347 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007348 SECOND_DISPLAY_ID, {110, 200}))
7349 << "Inject motion event should return InputEventInjectionResult::FAILED";
7350 windowInSecondary->assertNoEvents();
7351 monitorInSecondary.assertNoEvents();
7352}
7353
Hu Guocb134f12023-12-23 13:42:44 +00007354/**
7355 * Send a key to the primary display and to the secondary display.
7356 * Then cause the key on the primary display to be canceled by sending in a stale key.
7357 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7358 * does not get canceled.
7359 */
7360TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7361 // Send a key down on primary display
7362 mDispatcher->notifyKey(
7363 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7364 .displayId(ADISPLAY_ID_DEFAULT)
7365 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7366 .build());
7367 windowInPrimary->consumeKeyEvent(
7368 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7369 windowInSecondary->assertNoEvents();
7370
7371 // Send a key down on second display
7372 mDispatcher->notifyKey(
7373 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7374 .displayId(SECOND_DISPLAY_ID)
7375 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7376 .build());
7377 windowInSecondary->consumeKeyEvent(
7378 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7379 windowInPrimary->assertNoEvents();
7380
7381 // Send a valid key up event on primary display that will be dropped because it is stale
7382 NotifyKeyArgs staleKeyUp =
7383 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7384 .displayId(ADISPLAY_ID_DEFAULT)
7385 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7386 .build();
7387 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7388 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7389 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7390 mDispatcher->notifyKey(staleKeyUp);
7391
7392 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7393 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7394 // receive any events.
7395 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7396 WithDisplayId(ADISPLAY_ID_DEFAULT),
7397 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7398 windowInSecondary->assertNoEvents();
7399}
7400
7401/**
7402 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7403 */
7404TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7405 // Send touch down on primary display.
7406 mDispatcher->notifyMotion(
7407 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7408 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7409 .displayId(ADISPLAY_ID_DEFAULT)
7410 .build());
7411 windowInPrimary->consumeMotionEvent(
7412 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7413 windowInSecondary->assertNoEvents();
7414
7415 // Send touch down on second display.
7416 mDispatcher->notifyMotion(
7417 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7418 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7419 .displayId(SECOND_DISPLAY_ID)
7420 .build());
7421 windowInPrimary->assertNoEvents();
7422 windowInSecondary->consumeMotionEvent(
7423 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7424
7425 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7426 NotifyMotionArgs staleMotionUp =
7427 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7428 .displayId(ADISPLAY_ID_DEFAULT)
7429 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7430 .build();
7431 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7432 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7433 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7434 mDispatcher->notifyMotion(staleMotionUp);
7435
7436 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7437 // events, where we would cancel the current keys instead.
7438 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7439 windowInSecondary->assertNoEvents();
7440}
7441
Jackal Guof9696682018-10-05 12:23:23 +08007442class InputFilterTest : public InputDispatcherTest {
7443protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007444 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7445 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007446 NotifyMotionArgs motionArgs;
7447
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007448 motionArgs =
7449 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007450 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007451 motionArgs =
7452 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007453 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007454 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007455 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007456 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007457 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007458 } else {
7459 mFakePolicy->assertFilterInputEventWasNotCalled();
7460 }
7461 }
7462
7463 void testNotifyKey(bool expectToBeFiltered) {
7464 NotifyKeyArgs keyArgs;
7465
7466 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007467 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007468 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007469 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007470 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007471
7472 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007473 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007474 } else {
7475 mFakePolicy->assertFilterInputEventWasNotCalled();
7476 }
7477 }
7478};
7479
7480// Test InputFilter for MotionEvent
7481TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7482 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007483 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7484 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007485
7486 // Enable InputFilter
7487 mDispatcher->setInputFilterEnabled(true);
7488 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007489 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7490 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007491
7492 // Disable InputFilter
7493 mDispatcher->setInputFilterEnabled(false);
7494 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007495 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7496 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007497}
7498
7499// Test InputFilter for KeyEvent
7500TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7501 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007502 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007503
7504 // Enable InputFilter
7505 mDispatcher->setInputFilterEnabled(true);
7506 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007507 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007508
7509 // Disable InputFilter
7510 mDispatcher->setInputFilterEnabled(false);
7511 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007512 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007513}
7514
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007515// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7516// logical display coordinate space.
7517TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7518 ui::Transform firstDisplayTransform;
7519 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7520 ui::Transform secondDisplayTransform;
7521 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7522
7523 std::vector<gui::DisplayInfo> displayInfos(2);
7524 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7525 displayInfos[0].transform = firstDisplayTransform;
7526 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7527 displayInfos[1].transform = secondDisplayTransform;
7528
Patrick Williamsd828f302023-04-28 17:52:08 -05007529 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007530
7531 // Enable InputFilter
7532 mDispatcher->setInputFilterEnabled(true);
7533
7534 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007535 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7536 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007537}
7538
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007539class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7540protected:
7541 virtual void SetUp() override {
7542 InputDispatcherTest::SetUp();
7543
7544 /**
7545 * We don't need to enable input filter to test the injected event policy, but we enabled it
7546 * here to make the tests more realistic, since this policy only matters when inputfilter is
7547 * on.
7548 */
7549 mDispatcher->setInputFilterEnabled(true);
7550
7551 std::shared_ptr<InputApplicationHandle> application =
7552 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007553 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7554 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007555
7556 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7557 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007558 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007559 setFocusedWindow(mWindow);
7560 mWindow->consumeFocusEvent(true);
7561 }
7562
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007563 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7564 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007565 KeyEvent event;
7566
7567 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7568 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7569 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007570 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007571 const int32_t additionalPolicyFlags =
7572 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007574 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007575 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007576 policyFlags | additionalPolicyFlags));
7577
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007578 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007579 }
7580
7581 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7582 int32_t flags) {
7583 MotionEvent event;
7584 PointerProperties pointerProperties[1];
7585 PointerCoords pointerCoords[1];
7586 pointerProperties[0].clear();
7587 pointerProperties[0].id = 0;
7588 pointerCoords[0].clear();
7589 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7590 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7591
7592 ui::Transform identityTransform;
7593 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7594 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7595 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7596 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7597 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007598 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007599 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007600 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007601
7602 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007604 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007605 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007606 policyFlags | additionalPolicyFlags));
7607
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007608 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007609 }
7610
7611private:
7612 sp<FakeWindowHandle> mWindow;
7613};
7614
7615TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007616 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7617 // filter. Without it, the event will no different from a regularly injected event, and the
7618 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007619 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7620 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007621}
7622
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007623TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007624 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007625 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007626 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7627}
7628
7629TEST_F(InputFilterInjectionPolicyTest,
7630 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7631 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007632 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007633 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007634}
7635
7636TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007637 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7638 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007639}
7640
chaviwfd6d3512019-03-25 13:23:49 -07007641class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007642 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007643 InputDispatcherTest::SetUp();
7644
Chris Yea209fde2020-07-22 13:54:51 -07007645 std::shared_ptr<FakeApplicationHandle> application =
7646 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007647 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007648 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007649 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007650
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007651 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007652 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007653 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007654
7655 // Set focused application.
7656 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007657 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007658
7659 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007660 mDispatcher->onWindowInfosChanged(
7661 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007662 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007663 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007664 }
7665
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007666 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007667 InputDispatcherTest::TearDown();
7668
7669 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007670 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007671 }
7672
7673protected:
7674 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007675 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007676 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007677};
7678
7679// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7680// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7681// the onPointerDownOutsideFocus callback.
7682TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007684 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007685 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007687 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007688
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007689 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007690 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7691}
7692
7693// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7694// DOWN on the window that doesn't have focus. Ensure no window received the
7695// onPointerDownOutsideFocus callback.
7696TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007698 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7699 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007701 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007702
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007703 ASSERT_TRUE(mDispatcher->waitForIdle());
7704 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007705}
7706
7707// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7708// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7709TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007711 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007712 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007713 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007714
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007715 ASSERT_TRUE(mDispatcher->waitForIdle());
7716 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007717}
7718
7719// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7720// DOWN on the window that already has focus. Ensure no window received the
7721// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007722TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007724 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007725 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007727 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007728
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007729 ASSERT_TRUE(mDispatcher->waitForIdle());
7730 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007731}
7732
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007733// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7734// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7735TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7736 const MotionEvent event =
7737 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7738 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007739 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007740 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7741 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7744 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7745
7746 ASSERT_TRUE(mDispatcher->waitForIdle());
7747 mFakePolicy->assertOnPointerDownWasNotCalled();
7748 // Ensure that the unfocused window did not receive any FOCUS events.
7749 mUnfocusedWindow->assertNoEvents();
7750}
7751
chaviwaf87b3e2019-10-01 16:59:28 -07007752// These tests ensures we can send touch events to a single client when there are multiple input
7753// windows that point to the same client token.
7754class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7755 virtual void SetUp() override {
7756 InputDispatcherTest::SetUp();
7757
Chris Yea209fde2020-07-22 13:54:51 -07007758 std::shared_ptr<FakeApplicationHandle> application =
7759 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007760 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7761 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007762 mWindow1->setFrame(Rect(0, 0, 100, 100));
7763
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007764 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007765 mWindow2->setFrame(Rect(100, 100, 200, 200));
7766
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007767 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007768 }
7769
7770protected:
7771 sp<FakeWindowHandle> mWindow1;
7772 sp<FakeWindowHandle> mWindow2;
7773
7774 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007775 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007776 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7777 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007778 }
7779
7780 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7781 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007782 const std::string name = window->getName();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007783 const MotionEvent& motionEvent =
7784 window->consumeMotionEvent(WithMotionAction(expectedAction));
chaviwaf87b3e2019-10-01 16:59:28 -07007785
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007786 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007787
7788 for (size_t i = 0; i < points.size(); i++) {
7789 float expectedX = points[i].x;
7790 float expectedY = points[i].y;
7791
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007792 EXPECT_EQ(expectedX, motionEvent.getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007793 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007794 << ", got " << motionEvent.getX(i);
7795 EXPECT_EQ(expectedY, motionEvent.getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007796 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007797 << ", got " << motionEvent.getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007798 }
7799 }
chaviw9eaa22c2020-07-01 16:21:27 -07007800
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007801 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007802 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007803 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7804 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007805
7806 // Always consume from window1 since it's the window that has the InputReceiver
7807 consumeMotionEvent(mWindow1, action, expectedPoints);
7808 }
chaviwaf87b3e2019-10-01 16:59:28 -07007809};
7810
7811TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7812 // Touch Window 1
7813 PointF touchedPoint = {10, 10};
7814 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007815 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007816
7817 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007818 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007819
7820 // Touch Window 2
7821 touchedPoint = {150, 150};
7822 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007823 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007824}
7825
chaviw9eaa22c2020-07-01 16:21:27 -07007826TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7827 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007828 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007829 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007830
7831 // Touch Window 1
7832 PointF touchedPoint = {10, 10};
7833 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007834 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007835 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007836 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007837
7838 // Touch Window 2
7839 touchedPoint = {150, 150};
7840 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007841 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7842 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007843
chaviw9eaa22c2020-07-01 16:21:27 -07007844 // Update the transform so rotation is set
7845 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007846 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007847 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7848 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007849}
7850
chaviw9eaa22c2020-07-01 16:21:27 -07007851TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007852 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007853 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007854
7855 // Touch Window 1
7856 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7857 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007858 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007859
7860 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007861 touchedPoints.push_back(PointF{150, 150});
7862 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007863 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007864
chaviw9eaa22c2020-07-01 16:21:27 -07007865 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007866 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007867 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007868
chaviw9eaa22c2020-07-01 16:21:27 -07007869 // Update the transform so rotation is set for Window 2
7870 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007871 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007872 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007873 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007874}
7875
chaviw9eaa22c2020-07-01 16:21:27 -07007876TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007877 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007878 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007879
7880 // Touch Window 1
7881 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7882 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007883 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007884
7885 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007886 touchedPoints.push_back(PointF{150, 150});
7887 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007888
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007889 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007890
7891 // Move both windows
7892 touchedPoints = {{20, 20}, {175, 175}};
7893 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7894 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7895
chaviw9eaa22c2020-07-01 16:21:27 -07007896 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007897
chaviw9eaa22c2020-07-01 16:21:27 -07007898 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007899 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007900 expectedPoints.pop_back();
7901
7902 // Touch Window 2
7903 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007904 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007905 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007906 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007907
7908 // Move both windows
7909 touchedPoints = {{20, 20}, {175, 175}};
7910 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7911 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7912
7913 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007914}
7915
7916TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7917 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007918 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007919
7920 // Touch Window 1
7921 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7922 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007923 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007924
7925 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007926 touchedPoints.push_back(PointF{150, 150});
7927 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007928
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007929 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007930
7931 // Move both windows
7932 touchedPoints = {{20, 20}, {175, 175}};
7933 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7934 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7935
chaviw9eaa22c2020-07-01 16:21:27 -07007936 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007937}
7938
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007939/**
7940 * When one of the windows is slippery, the touch should not slip into the other window with the
7941 * same input channel.
7942 */
7943TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7944 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007945 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007946
7947 // Touch down in window 1
7948 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7949 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7950 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7951
7952 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7953 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7954 // getting generated.
7955 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7956 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7957
7958 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7959}
7960
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007961/**
7962 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7963 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7964 * that the pointer is hovering over may have a different transform.
7965 */
7966TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007967 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007968
7969 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7971 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7972 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007973 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7974 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007975 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7977 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7978 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007979 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7980 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7981 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7982}
7983
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007984class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7985 virtual void SetUp() override {
7986 InputDispatcherTest::SetUp();
7987
Chris Yea209fde2020-07-22 13:54:51 -07007988 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007989 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007990 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7991 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007992 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007993 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007994 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007995
7996 // Set focused application.
7997 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7998
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007999 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008000 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008001 mWindow->consumeFocusEvent(true);
8002 }
8003
8004 virtual void TearDown() override {
8005 InputDispatcherTest::TearDown();
8006 mWindow.clear();
8007 }
8008
8009protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008010 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008011 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008012 sp<FakeWindowHandle> mWindow;
8013 static constexpr PointF WINDOW_LOCATION = {20, 20};
8014
8015 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008016 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8017 .x(WINDOW_LOCATION.x)
8018 .y(WINDOW_LOCATION.y);
8019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8020 .pointer(touchingPointer)
8021 .build());
8022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8023 .pointer(touchingPointer)
8024 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008025 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008026
8027 sp<FakeWindowHandle> addSpyWindow() {
8028 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008029 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008030 spy->setTrustedOverlay(true);
8031 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008032 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008033 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008034 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008035 return spy;
8036 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008037};
8038
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008039// Send a tap and respond, which should not cause an ANR.
8040TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8041 tapOnWindow();
8042 mWindow->consumeMotionDown();
8043 mWindow->consumeMotionUp();
8044 ASSERT_TRUE(mDispatcher->waitForIdle());
8045 mFakePolicy->assertNotifyAnrWasNotCalled();
8046}
8047
8048// Send a regular key and respond, which should not cause an ANR.
8049TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008051 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8052 ASSERT_TRUE(mDispatcher->waitForIdle());
8053 mFakePolicy->assertNotifyAnrWasNotCalled();
8054}
8055
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008056TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8057 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008058 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008059 mWindow->consumeFocusEvent(false);
8060
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008061 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008062 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8063 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008064 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008066 // Key will not go to window because we have no focused window.
8067 // The 'no focused window' ANR timer should start instead.
8068
8069 // Now, the focused application goes away.
8070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8071 // The key should get dropped and there should be no ANR.
8072
8073 ASSERT_TRUE(mDispatcher->waitForIdle());
8074 mFakePolicy->assertNotifyAnrWasNotCalled();
8075}
8076
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008077// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008078// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8079// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008080TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008082 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008083 WINDOW_LOCATION));
8084
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008085 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8086 ASSERT_TRUE(sequenceNum);
8087 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008088 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008089
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008091 mWindow->consumeMotionEvent(
8092 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008093 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008094 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008095}
8096
8097// Send a key to the app and have the app not respond right away.
8098TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8099 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008101 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
8102 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008103 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008104 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008105 ASSERT_TRUE(mDispatcher->waitForIdle());
8106}
8107
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008108// We have a focused application, but no focused window
8109TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008110 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008111 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008112 mWindow->consumeFocusEvent(false);
8113
8114 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008116 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008117 WINDOW_LOCATION));
8118 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8119 mDispatcher->waitForIdle();
8120 mFakePolicy->assertNotifyAnrWasNotCalled();
8121
8122 // Once a focused event arrives, we get an ANR for this application
8123 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8124 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008125 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008126 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008127 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008128 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008129 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008130 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131 ASSERT_TRUE(mDispatcher->waitForIdle());
8132}
8133
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008134/**
8135 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8136 * there will not be an ANR.
8137 */
8138TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8139 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008140 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008141 mWindow->consumeFocusEvent(false);
8142
8143 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008144 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8145 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008146 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8147 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8148
8149 // Define a valid key down event that is stale (too old).
8150 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008151 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008152 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008153
8154 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8155
8156 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008157 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008158 InputEventInjectionSync::WAIT_FOR_RESULT,
8159 INJECT_EVENT_TIMEOUT, policyFlags);
8160 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8161 << "Injection should fail because the event is stale";
8162
8163 ASSERT_TRUE(mDispatcher->waitForIdle());
8164 mFakePolicy->assertNotifyAnrWasNotCalled();
8165 mWindow->assertNoEvents();
8166}
8167
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008168// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008169// Make sure that we don't notify policy twice about the same ANR.
8170TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008171 const std::chrono::duration appTimeout = 400ms;
8172 mApplication->setDispatchingTimeout(appTimeout);
8173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8174
Vishnu Nair47074b82020-08-14 11:54:47 -07008175 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008176 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008177 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008178
8179 // Once a focused event arrives, we get an ANR for this application
8180 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8181 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008182 const std::chrono::duration eventInjectionTimeout = 100ms;
8183 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008184 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008185 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008186 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8187 /*allowKeyRepeat=*/false);
8188 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8189 << "result=" << ftl::enum_string(result);
8190 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8191 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8192 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8193 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194
Vishnu Naire4df8752022-09-08 09:17:55 -07008195 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008196 // ANR should not be raised again. It is up to policy to do that if it desires.
8197 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008198
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008199 // If we now get a focused window, the ANR should stop, but the policy handles that via
8200 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008201 ASSERT_TRUE(mDispatcher->waitForIdle());
8202}
8203
8204// We have a focused application, but no focused window
8205TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008206 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008207 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208 mWindow->consumeFocusEvent(false);
8209
8210 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008211 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008212
Vishnu Naire4df8752022-09-08 09:17:55 -07008213 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8214 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008215
8216 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008217 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008218 ASSERT_TRUE(mDispatcher->waitForIdle());
8219 mWindow->assertNoEvents();
8220}
8221
8222/**
8223 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8224 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8225 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8226 * the ANR mechanism should still work.
8227 *
8228 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8229 * DOWN event, while not responding on the second one.
8230 */
8231TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8232 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008233 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008234 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8235 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8236 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008237 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008238
8239 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008240 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008241 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8242 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8243 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008244 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008245
8246 // We have now sent down and up. Let's consume first event and then ANR on the second.
8247 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8248 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008249 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008250}
8251
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008252// A spy window can receive an ANR
8253TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8254 sp<FakeWindowHandle> spy = addSpyWindow();
8255
8256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008257 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008258 WINDOW_LOCATION));
8259 mWindow->consumeMotionDown();
8260
8261 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8262 ASSERT_TRUE(sequenceNum);
8263 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008264 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008265
8266 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008267 spy->consumeMotionEvent(
8268 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008269 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008270 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008271}
8272
8273// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008274// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008275TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8276 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008277
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008279 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008282
8283 // Stuck on the ACTION_UP
8284 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008285 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008286
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008287 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008288 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008289 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8290 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291
8292 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8293 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008294 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008295 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008296 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008297}
8298
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008299// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008300// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008301TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8302 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008303
8304 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008305 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8306 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008307
8308 mWindow->consumeMotionDown();
8309 // Stuck on the ACTION_UP
8310 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008311 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008312
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008313 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008314 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008315 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8316 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008317
8318 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8319 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008320 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008321 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008322 spy->assertNoEvents();
8323}
8324
8325TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008326 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008327
Prabir Pradhanfb549072023-10-05 19:17:36 +00008328 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008329
8330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008331 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008332 WINDOW_LOCATION));
8333
8334 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8335 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8336 ASSERT_TRUE(consumeSeq);
8337
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008338 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8339 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008340
8341 monitor.finishEvent(*consumeSeq);
8342 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8343
8344 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008345 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008346}
8347
8348// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8349// process events, you don't get an anr. When the window later becomes unresponsive again, you
8350// get an ANR again.
8351// 1. tap -> block on ACTION_UP -> receive ANR
8352// 2. consume all pending events (= queue becomes healthy again)
8353// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8354TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8355 tapOnWindow();
8356
8357 mWindow->consumeMotionDown();
8358 // Block on ACTION_UP
8359 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008360 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008361 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8362 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008363 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008364 mWindow->assertNoEvents();
8365
8366 tapOnWindow();
8367 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008368 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008369 mWindow->consumeMotionUp();
8370
8371 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008372 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008373 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008374 mWindow->assertNoEvents();
8375}
8376
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008377// If a connection remains unresponsive for a while, make sure policy is only notified once about
8378// it.
8379TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008381 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008382 WINDOW_LOCATION));
8383
8384 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008385 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008386 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008387 // 'notifyConnectionUnresponsive' should only be called once per connection
8388 mFakePolicy->assertNotifyAnrWasNotCalled();
8389 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008390 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008391 mWindow->consumeMotionEvent(
8392 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008393 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008394 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008395 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008396 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397}
8398
8399/**
8400 * 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 -07008401 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008402 *
8403 * Warning!!!
8404 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8405 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008406 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008407 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8408 *
8409 * If that value changes, this test should also change.
8410 */
8411TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8412 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008413 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008414
8415 tapOnWindow();
8416 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8417 ASSERT_TRUE(downSequenceNum);
8418 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8419 ASSERT_TRUE(upSequenceNum);
8420 // Don't finish the events yet, and send a key
8421 // Injection will "succeed" because we will eventually give up and send the key to the focused
8422 // window even if motions are still being processed. But because the injection timeout is short,
8423 // we will receive INJECTION_TIMED_OUT as the result.
8424
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008425 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008426 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8427 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008428 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008429 // Key will not be sent to the window, yet, because the window is still processing events
8430 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008431 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8432 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8433 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8434 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008435
8436 std::this_thread::sleep_for(500ms);
8437 // if we wait long enough though, dispatcher will give up, and still send the key
8438 // to the focused window, even though we have not yet finished the motion event
8439 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8440 mWindow->finishEvent(*downSequenceNum);
8441 mWindow->finishEvent(*upSequenceNum);
8442}
8443
8444/**
8445 * If a window is processing a motion event, and then a key event comes in, the key event should
8446 * not go to the focused window until the motion is processed.
8447 * If then a new motion comes in, then the pending key event should be going to the currently
8448 * focused window right away.
8449 */
8450TEST_F(InputDispatcherSingleWindowAnr,
8451 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8452 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008453 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008454
8455 tapOnWindow();
8456 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8457 ASSERT_TRUE(downSequenceNum);
8458 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8459 ASSERT_TRUE(upSequenceNum);
8460 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008461 mDispatcher->notifyKey(
8462 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8463 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8464 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008465 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008466 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8467 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8468 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8469 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008470
8471 // Now tap down again. It should cause the pending key to go to the focused window right away.
8472 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008473 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8474 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008475 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8476 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008477 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8478 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008479 mWindow->assertNoEvents();
8480}
8481
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008482/**
8483 * Send an event to the app and have the app not respond right away.
8484 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8485 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8486 * At some point, the window becomes responsive again.
8487 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8488 */
8489TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8491 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8492 .build());
8493
8494 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8495 ASSERT_TRUE(sequenceNum);
8496 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8497 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8498
8499 mWindow->finishEvent(*sequenceNum);
8500 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8501 ASSERT_TRUE(mDispatcher->waitForIdle());
8502 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8503
8504 // Now that the window is responsive, let's continue the gesture.
8505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8506 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8507 .build());
8508
8509 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8510 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8511 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8512 .build());
8513
8514 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8515 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8516 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8517 .build());
8518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8519 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8520 .build());
8521 // We already canceled this pointer, so the window shouldn't get any new events.
8522 mWindow->assertNoEvents();
8523
8524 // Start another one.
8525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8526 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8527 .build());
8528 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8529}
8530
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008531class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8532 virtual void SetUp() override {
8533 InputDispatcherTest::SetUp();
8534
Chris Yea209fde2020-07-22 13:54:51 -07008535 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008536 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008537 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8538 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008539 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008540 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008541 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008542
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008543 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8544 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008545 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008546 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008547
8548 // Set focused application.
8549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008550 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008551
8552 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008553 mDispatcher->onWindowInfosChanged(
8554 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008555 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008556 mFocusedWindow->consumeFocusEvent(true);
8557 }
8558
8559 virtual void TearDown() override {
8560 InputDispatcherTest::TearDown();
8561
8562 mUnfocusedWindow.clear();
8563 mFocusedWindow.clear();
8564 }
8565
8566protected:
Chris Yea209fde2020-07-22 13:54:51 -07008567 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008568 sp<FakeWindowHandle> mUnfocusedWindow;
8569 sp<FakeWindowHandle> mFocusedWindow;
8570 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8571 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8572 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8573
8574 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8575
8576 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8577
8578private:
8579 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008581 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008582 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008584 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008585 location));
8586 }
8587};
8588
8589// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8590// should be ANR'd first.
8591TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008593 injectMotionEvent(*mDispatcher,
8594 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8595 AINPUT_SOURCE_TOUCHSCREEN)
8596 .pointer(PointerBuilder(0, ToolType::FINGER)
8597 .x(FOCUSED_WINDOW_LOCATION.x)
8598 .y(FOCUSED_WINDOW_LOCATION.y))
8599 .build()));
8600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8601 injectMotionEvent(*mDispatcher,
8602 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8603 AINPUT_SOURCE_TOUCHSCREEN)
8604 .pointer(PointerBuilder(0, ToolType::FINGER)
8605 .x(FOCUSED_WINDOW_LOCATION.x)
8606 .y(FOCUSED_WINDOW_LOCATION.y))
8607 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008608 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008609 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008610 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008611 // We consumed all events, so no ANR
8612 ASSERT_TRUE(mDispatcher->waitForIdle());
8613 mFakePolicy->assertNotifyAnrWasNotCalled();
8614
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008616 injectMotionEvent(*mDispatcher,
8617 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8618 AINPUT_SOURCE_TOUCHSCREEN)
8619 .pointer(PointerBuilder(0, ToolType::FINGER)
8620 .x(FOCUSED_WINDOW_LOCATION.x)
8621 .y(FOCUSED_WINDOW_LOCATION.y))
8622 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008623 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8624 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008625
8626 const std::chrono::duration timeout =
8627 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008628 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008629
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008630 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008631 mFocusedWindow->consumeMotionDown();
8632 // This cancel is generated because the connection was unresponsive
8633 mFocusedWindow->consumeMotionCancel();
8634 mFocusedWindow->assertNoEvents();
8635 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008636 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008637 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8638 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008639 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008640}
8641
8642// If we have 2 windows with identical timeouts that are both unresponsive,
8643// it doesn't matter which order they should have ANR.
8644// But we should receive ANR for both.
8645TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8646 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008647 mUnfocusedWindow->setDispatchingTimeout(
8648 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008649 mDispatcher->onWindowInfosChanged(
8650 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008651
8652 tapOnFocusedWindow();
8653 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008654 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008655 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8656 mFocusedWindow->getDispatchingTimeout(
8657 DISPATCHING_TIMEOUT)),
8658 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8659
8660 ASSERT_THAT(anrConnectionTokens,
8661 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8662 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663
8664 ASSERT_TRUE(mDispatcher->waitForIdle());
8665 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008666
8667 mFocusedWindow->consumeMotionDown();
8668 mFocusedWindow->consumeMotionUp();
8669 mUnfocusedWindow->consumeMotionOutside();
8670
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008671 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8672 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008673
8674 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008675 ASSERT_THAT(responsiveTokens,
8676 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8677 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008678 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008679}
8680
8681// If a window is already not responding, the second tap on the same window should be ignored.
8682// We should also log an error to account for the dropped event (not tested here).
8683// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8684TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8685 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008686 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008687 // Receive the events, but don't respond
8688 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8689 ASSERT_TRUE(downEventSequenceNum);
8690 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8691 ASSERT_TRUE(upEventSequenceNum);
8692 const std::chrono::duration timeout =
8693 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008694 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008695
8696 // Tap once again
8697 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008698 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008699 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008700 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008701 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008702 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008703 FOCUSED_WINDOW_LOCATION));
8704 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8705 // valid touch target
8706 mUnfocusedWindow->assertNoEvents();
8707
8708 // Consume the first tap
8709 mFocusedWindow->finishEvent(*downEventSequenceNum);
8710 mFocusedWindow->finishEvent(*upEventSequenceNum);
8711 ASSERT_TRUE(mDispatcher->waitForIdle());
8712 // The second tap did not go to the focused window
8713 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008714 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008715 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8716 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008717 mFakePolicy->assertNotifyAnrWasNotCalled();
8718}
8719
8720// If you tap outside of all windows, there will not be ANR
8721TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008722 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008723 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008724 LOCATION_OUTSIDE_ALL_WINDOWS));
8725 ASSERT_TRUE(mDispatcher->waitForIdle());
8726 mFakePolicy->assertNotifyAnrWasNotCalled();
8727}
8728
8729// Since the focused window is paused, tapping on it should not produce any events
8730TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8731 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008732 mDispatcher->onWindowInfosChanged(
8733 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008734
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008736 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008737 FOCUSED_WINDOW_LOCATION));
8738
8739 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8740 ASSERT_TRUE(mDispatcher->waitForIdle());
8741 // Should not ANR because the window is paused, and touches shouldn't go to it
8742 mFakePolicy->assertNotifyAnrWasNotCalled();
8743
8744 mFocusedWindow->assertNoEvents();
8745 mUnfocusedWindow->assertNoEvents();
8746}
8747
8748/**
8749 * 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 -07008750 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008751 * If a different window becomes focused at this time, the key should go to that window instead.
8752 *
8753 * Warning!!!
8754 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8755 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008756 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008757 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8758 *
8759 * If that value changes, this test should also change.
8760 */
8761TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8762 // Set a long ANR timeout to prevent it from triggering
8763 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008764 mDispatcher->onWindowInfosChanged(
8765 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008766
8767 tapOnUnfocusedWindow();
8768 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8769 ASSERT_TRUE(downSequenceNum);
8770 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8771 ASSERT_TRUE(upSequenceNum);
8772 // Don't finish the events yet, and send a key
8773 // Injection will succeed because we will eventually give up and send the key to the focused
8774 // window even if motions are still being processed.
8775
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008776 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008777 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8778 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008780 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008781 // and the key remains pending, waiting for the touch events to be processed.
8782 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8783 // under the hood.
8784 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8785 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008786
8787 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008788 mFocusedWindow->setFocusable(false);
8789 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008790 mDispatcher->onWindowInfosChanged(
8791 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008792 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008793
8794 // Focus events should precede the key events
8795 mUnfocusedWindow->consumeFocusEvent(true);
8796 mFocusedWindow->consumeFocusEvent(false);
8797
8798 // Finish the tap events, which should unblock dispatcher
8799 mUnfocusedWindow->finishEvent(*downSequenceNum);
8800 mUnfocusedWindow->finishEvent(*upSequenceNum);
8801
8802 // Now that all queues are cleared and no backlog in the connections, the key event
8803 // can finally go to the newly focused "mUnfocusedWindow".
8804 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8805 mFocusedWindow->assertNoEvents();
8806 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008807 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008808}
8809
8810// When the touch stream is split across 2 windows, and one of them does not respond,
8811// then ANR should be raised and the touch should be canceled for the unresponsive window.
8812// The other window should not be affected by that.
8813TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8814 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008815 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8816 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8817 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008818 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008819
8820 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008821 mDispatcher->notifyMotion(
8822 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8823 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008824
8825 const std::chrono::duration timeout =
8826 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008827 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008828
8829 mUnfocusedWindow->consumeMotionDown();
8830 mFocusedWindow->consumeMotionDown();
8831 // Focused window may or may not receive ACTION_MOVE
8832 // But it should definitely receive ACTION_CANCEL due to the ANR
8833 InputEvent* event;
8834 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8835 ASSERT_TRUE(moveOrCancelSequenceNum);
8836 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8837 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008838 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008839 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8840 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8841 mFocusedWindow->consumeMotionCancel();
8842 } else {
8843 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8844 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008845 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008846 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8847 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008848
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008849 mUnfocusedWindow->assertNoEvents();
8850 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008851 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008852}
8853
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008854/**
8855 * If we have no focused window, and a key comes in, we start the ANR timer.
8856 * The focused application should add a focused window before the timer runs out to prevent ANR.
8857 *
8858 * If the user touches another application during this time, the key should be dropped.
8859 * Next, if a new focused window comes in, without toggling the focused application,
8860 * then no ANR should occur.
8861 *
8862 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8863 * but in some cases the policy may not update the focused application.
8864 */
8865TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8866 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8867 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008868 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008869 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8870 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8871 mFocusedWindow->setFocusable(false);
8872
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008873 mDispatcher->onWindowInfosChanged(
8874 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008875 mFocusedWindow->consumeFocusEvent(false);
8876
8877 // Send a key. The ANR timer should start because there is no focused window.
8878 // 'focusedApplication' will get blamed if this timer completes.
8879 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008880 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008881 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8882 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008883 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008885
8886 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8887 // then the injected touches won't cause the focused event to get dropped.
8888 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8889 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8890 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8891 // For this test, it means that the key would get delivered to the window once it becomes
8892 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008893 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008894
8895 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008896 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8897 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8898 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008899
8900 // We do not consume the motion right away, because that would require dispatcher to first
8901 // process (== drop) the key event, and by that time, ANR will be raised.
8902 // Set the focused window first.
8903 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008904 mDispatcher->onWindowInfosChanged(
8905 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008906 setFocusedWindow(mFocusedWindow);
8907 mFocusedWindow->consumeFocusEvent(true);
8908 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8909 // to another application. This could be a bug / behaviour in the policy.
8910
8911 mUnfocusedWindow->consumeMotionDown();
8912
8913 ASSERT_TRUE(mDispatcher->waitForIdle());
8914 // Should not ANR because we actually have a focused window. It was just added too slowly.
8915 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8916}
8917
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08008918/**
8919 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8920 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8921 * dispatcher doesn't prune pointer events incorrectly.
8922 *
8923 * This test reproduces a crash in InputDispatcher.
8924 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8925 *
8926 * Keep the currently focused application (mApplication), and have no focused window.
8927 * We set up two additional windows:
8928 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8929 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8930 * window. This window is not focusable, but is touchable.
8931 *
8932 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8933 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8934 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8935 *
8936 * Now, we touch "Another window". This window is owned by a different application than
8937 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8938 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8939 * dropping the events from its queue. Ensure that no crash occurs.
8940 *
8941 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8942 * This does not affect the test running time.
8943 */
8944TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8945 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8946 std::make_shared<FakeApplicationHandle>();
8947 systemUiApplication->setDispatchingTimeout(3000ms);
8948 mFakePolicy->setStaleEventTimeout(3000ms);
8949 sp<FakeWindowHandle> navigationBar =
8950 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
8951 ADISPLAY_ID_DEFAULT);
8952 navigationBar->setFocusable(false);
8953 navigationBar->setWatchOutsideTouch(true);
8954 navigationBar->setFrame(Rect(0, 0, 100, 100));
8955
8956 mApplication->setDispatchingTimeout(3000ms);
8957 // 'mApplication' is already focused, but we call it again here to make it explicit.
8958 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8959
8960 std::shared_ptr<FakeApplicationHandle> anotherApplication =
8961 std::make_shared<FakeApplicationHandle>();
8962 sp<FakeWindowHandle> appWindow =
8963 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
8964 ADISPLAY_ID_DEFAULT);
8965 appWindow->setFocusable(false);
8966 appWindow->setFrame(Rect(100, 100, 200, 200));
8967
8968 mDispatcher->onWindowInfosChanged(
8969 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
8970 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
8971 mFocusedWindow->consumeFocusEvent(false);
8972
8973 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
8974 // in response.
8975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8976 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8977 .build());
8978 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8979
8980 // Key will not be sent anywhere because we have no focused window. It will remain pending.
8981 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
8982 InputEventInjectionResult result =
8983 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8984 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8985 /*allowKeyRepeat=*/false);
8986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8987
8988 // Finish the gesture - lift up finger and inject ACTION_UP key event
8989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8990 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8991 .build());
8992 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8993 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8994 /*allowKeyRepeat=*/false);
8995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8996 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
8997 // getting any events yet.
8998 navigationBar->assertNoEvents();
8999
9000 // Now touch "Another window". This touch is going to a different application than the one we
9001 // are waiting for (which is 'mApplication').
9002 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9003 // trying to be injected) and to continue processing the rest of the events in the original
9004 // order.
9005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9006 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9007 .build());
9008 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9009 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9010 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9011
9012 appWindow->assertNoEvents();
9013 navigationBar->assertNoEvents();
9014}
9015
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009016// These tests ensure we cannot send touch events to a window that's positioned behind a window
9017// that has feature NO_INPUT_CHANNEL.
9018// Layout:
9019// Top (closest to user)
9020// mNoInputWindow (above all windows)
9021// mBottomWindow
9022// Bottom (furthest from user)
9023class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9024 virtual void SetUp() override {
9025 InputDispatcherTest::SetUp();
9026
9027 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009028 mNoInputWindow =
9029 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9030 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009031 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009032 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009033 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9034 // It's perfectly valid for this window to not have an associated input channel
9035
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009036 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9037 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009038 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9039
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009040 mDispatcher->onWindowInfosChanged(
9041 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009042 }
9043
9044protected:
9045 std::shared_ptr<FakeApplicationHandle> mApplication;
9046 sp<FakeWindowHandle> mNoInputWindow;
9047 sp<FakeWindowHandle> mBottomWindow;
9048};
9049
9050TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9051 PointF touchedPoint = {10, 10};
9052
Prabir Pradhan678438e2023-04-13 19:32:51 +00009053 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9054 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9055 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009056
9057 mNoInputWindow->assertNoEvents();
9058 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9059 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9060 // and therefore should prevent mBottomWindow from receiving touches
9061 mBottomWindow->assertNoEvents();
9062}
9063
9064/**
9065 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9066 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9067 */
9068TEST_F(InputDispatcherMultiWindowOcclusionTests,
9069 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009070 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9071 "Window with input channel and NO_INPUT_CHANNEL",
9072 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009073
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009074 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009075 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009076 mDispatcher->onWindowInfosChanged(
9077 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009078
9079 PointF touchedPoint = {10, 10};
9080
Prabir Pradhan678438e2023-04-13 19:32:51 +00009081 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9082 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9083 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009084
9085 mNoInputWindow->assertNoEvents();
9086 mBottomWindow->assertNoEvents();
9087}
9088
Vishnu Nair958da932020-08-21 17:12:37 -07009089class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9090protected:
9091 std::shared_ptr<FakeApplicationHandle> mApp;
9092 sp<FakeWindowHandle> mWindow;
9093 sp<FakeWindowHandle> mMirror;
9094
9095 virtual void SetUp() override {
9096 InputDispatcherTest::SetUp();
9097 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009098 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009099 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9101 mWindow->setFocusable(true);
9102 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009103 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009104 }
9105};
9106
9107TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9108 // Request focus on a mirrored window
9109 setFocusedWindow(mMirror);
9110
9111 // window gets focused
9112 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009114 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009115 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9116}
9117
9118// A focused & mirrored window remains focused only if the window and its mirror are both
9119// focusable.
9120TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9121 setFocusedWindow(mMirror);
9122
9123 // window gets focused
9124 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009126 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009127 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009129 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009130 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9131
9132 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009133 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009134
9135 // window loses focus since one of the windows associated with the token in not focusable
9136 mWindow->consumeFocusEvent(false);
9137
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009138 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009139 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009140 mWindow->assertNoEvents();
9141}
9142
9143// A focused & mirrored window remains focused until the window and its mirror both become
9144// invisible.
9145TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9146 setFocusedWindow(mMirror);
9147
9148 // window gets focused
9149 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009151 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009152 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009154 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009155 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9156
9157 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009158 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009159
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009161 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009162 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009164 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009165 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9166
9167 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009168 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009169
9170 // window loses focus only after all windows associated with the token become invisible.
9171 mWindow->consumeFocusEvent(false);
9172
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009173 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009174 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009175 mWindow->assertNoEvents();
9176}
9177
9178// A focused & mirrored window remains focused until both windows are removed.
9179TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9180 setFocusedWindow(mMirror);
9181
9182 // window gets focused
9183 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009185 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009186 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009188 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009189 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9190
9191 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009193
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009195 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009196 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009198 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009199 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9200
9201 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009202 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009203 mWindow->consumeFocusEvent(false);
9204
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009205 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009206 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009207 mWindow->assertNoEvents();
9208}
9209
9210// Focus request can be pending until one window becomes visible.
9211TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9212 // Request focus on an invisible mirror.
9213 mWindow->setVisible(false);
9214 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009215 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009216 setFocusedWindow(mMirror);
9217
9218 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009220 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9221 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009222
9223 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009224 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009225
9226 // window gets focused
9227 mWindow->consumeFocusEvent(true);
9228 // window gets the pending key event
9229 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9230}
Prabir Pradhan99987712020-11-10 18:43:05 -08009231
9232class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9233protected:
9234 std::shared_ptr<FakeApplicationHandle> mApp;
9235 sp<FakeWindowHandle> mWindow;
9236 sp<FakeWindowHandle> mSecondWindow;
9237
9238 void SetUp() override {
9239 InputDispatcherTest::SetUp();
9240 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009241 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009242 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009243 mSecondWindow =
9244 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009245 mSecondWindow->setFocusable(true);
9246
9247 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009248 mDispatcher->onWindowInfosChanged(
9249 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009250
9251 setFocusedWindow(mWindow);
9252 mWindow->consumeFocusEvent(true);
9253 }
9254
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009255 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009256 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009257 }
9258
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009259 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9260 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009261 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009262 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9263 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009264 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009265 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009266 }
9267};
9268
9269TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9270 // Ensure that capture cannot be obtained for unfocused windows.
9271 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9272 mFakePolicy->assertSetPointerCaptureNotCalled();
9273 mSecondWindow->assertNoEvents();
9274
9275 // Ensure that capture can be enabled from the focus window.
9276 requestAndVerifyPointerCapture(mWindow, true);
9277
9278 // Ensure that capture cannot be disabled from a window that does not have capture.
9279 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9280 mFakePolicy->assertSetPointerCaptureNotCalled();
9281
9282 // Ensure that capture can be disabled from the window with capture.
9283 requestAndVerifyPointerCapture(mWindow, false);
9284}
9285
9286TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009287 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009288
9289 setFocusedWindow(mSecondWindow);
9290
9291 // Ensure that the capture disabled event was sent first.
9292 mWindow->consumeCaptureEvent(false);
9293 mWindow->consumeFocusEvent(false);
9294 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009295 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009296
9297 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009298 notifyPointerCaptureChanged({});
9299 notifyPointerCaptureChanged(request);
9300 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009301 mWindow->assertNoEvents();
9302 mSecondWindow->assertNoEvents();
9303 mFakePolicy->assertSetPointerCaptureNotCalled();
9304}
9305
9306TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009307 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009308
9309 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009310 notifyPointerCaptureChanged({});
9311 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009312
9313 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009314 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009315 mWindow->consumeCaptureEvent(false);
9316 mWindow->assertNoEvents();
9317}
9318
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009319TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9320 requestAndVerifyPointerCapture(mWindow, true);
9321
9322 // The first window loses focus.
9323 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009324 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009325 mWindow->consumeCaptureEvent(false);
9326
9327 // Request Pointer Capture from the second window before the notification from InputReader
9328 // arrives.
9329 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009330 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009331
9332 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009333 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009334
9335 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009336 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009337
9338 mSecondWindow->consumeFocusEvent(true);
9339 mSecondWindow->consumeCaptureEvent(true);
9340}
9341
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009342TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9343 // App repeatedly enables and disables capture.
9344 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9345 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9346 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9347 mFakePolicy->assertSetPointerCaptureCalled(false);
9348 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9349 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9350
9351 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9352 // first request is now stale, this should do nothing.
9353 notifyPointerCaptureChanged(firstRequest);
9354 mWindow->assertNoEvents();
9355
9356 // InputReader notifies that the second request was enabled.
9357 notifyPointerCaptureChanged(secondRequest);
9358 mWindow->consumeCaptureEvent(true);
9359}
9360
Prabir Pradhan7092e262022-05-03 16:51:09 +00009361TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9362 requestAndVerifyPointerCapture(mWindow, true);
9363
9364 // App toggles pointer capture off and on.
9365 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9366 mFakePolicy->assertSetPointerCaptureCalled(false);
9367
9368 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9369 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9370
9371 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9372 // preceding "disable" request.
9373 notifyPointerCaptureChanged(enableRequest);
9374
9375 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9376 // any notifications.
9377 mWindow->assertNoEvents();
9378}
9379
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009380/**
9381 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9382 * mouse movements don't affect the previous mouse hovering state.
9383 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9384 * HOVER_MOVE events).
9385 */
9386TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9387 // Mouse hover on the window
9388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9389 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9390 .build());
9391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9392 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9393 .build());
9394
9395 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9396 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9397
9398 // Start pointer capture
9399 requestAndVerifyPointerCapture(mWindow, true);
9400
9401 // Send some relative mouse movements and receive them in the window.
9402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9404 .build());
9405 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9406 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9407
9408 // Stop pointer capture
9409 requestAndVerifyPointerCapture(mWindow, false);
9410
9411 // Continue hovering on the window
9412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9414 .build());
9415 mWindow->consumeMotionEvent(
9416 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9417
9418 mWindow->assertNoEvents();
9419}
9420
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009421class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9422protected:
9423 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009424
9425 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9426 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9427
9428 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9429 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9430
9431 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9432 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9433 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9434 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9435 MAXIMUM_OBSCURING_OPACITY);
9436
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009437 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9438 static constexpr gui::Uid APP_B_UID{10002};
9439 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009440
9441 sp<FakeWindowHandle> mTouchWindow;
9442
9443 virtual void SetUp() override {
9444 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009445 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009446 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9447 }
9448
9449 virtual void TearDown() override {
9450 InputDispatcherTest::TearDown();
9451 mTouchWindow.clear();
9452 }
9453
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009454 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009455 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009456 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009457 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009458 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009459 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009460 return window;
9461 }
9462
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009463 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009464 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9465 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009466 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009467 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009468 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009469 return window;
9470 }
9471
9472 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009473 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9474 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9475 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009476 }
9477};
9478
9479TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009480 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009481 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009482 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009483
9484 touch();
9485
9486 mTouchWindow->assertNoEvents();
9487}
9488
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009489TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009490 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9491 const sp<FakeWindowHandle>& w =
9492 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009493 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009494
9495 touch();
9496
9497 mTouchWindow->assertNoEvents();
9498}
9499
9500TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009501 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9502 const sp<FakeWindowHandle>& w =
9503 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009504 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009505
9506 touch();
9507
9508 w->assertNoEvents();
9509}
9510
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009511TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009512 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009513 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009514
9515 touch();
9516
9517 mTouchWindow->consumeAnyMotionDown();
9518}
9519
9520TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009521 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009522 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009523 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009524 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009525
9526 touch({PointF{100, 100}});
9527
9528 mTouchWindow->consumeAnyMotionDown();
9529}
9530
9531TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009532 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009533 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009534 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009535
9536 touch();
9537
9538 mTouchWindow->consumeAnyMotionDown();
9539}
9540
9541TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9542 const sp<FakeWindowHandle>& w =
9543 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009544 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009545
9546 touch();
9547
9548 mTouchWindow->consumeAnyMotionDown();
9549}
9550
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009551TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9552 const sp<FakeWindowHandle>& w =
9553 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009554 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009555
9556 touch();
9557
9558 w->assertNoEvents();
9559}
9560
9561/**
9562 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9563 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9564 * window, the occluding window will still receive ACTION_OUTSIDE event.
9565 */
9566TEST_F(InputDispatcherUntrustedTouchesTest,
9567 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9568 const sp<FakeWindowHandle>& w =
9569 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009570 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009571 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009572
9573 touch();
9574
9575 w->consumeMotionOutside();
9576}
9577
9578TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9579 const sp<FakeWindowHandle>& w =
9580 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009581 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009582 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009583
9584 touch();
9585
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009586 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009587}
9588
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009589TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009590 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009591 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9592 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009593 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009594
9595 touch();
9596
9597 mTouchWindow->consumeAnyMotionDown();
9598}
9599
9600TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9601 const sp<FakeWindowHandle>& w =
9602 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9603 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009604 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009605
9606 touch();
9607
9608 mTouchWindow->consumeAnyMotionDown();
9609}
9610
9611TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009612 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009613 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9614 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009615 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009616
9617 touch();
9618
9619 mTouchWindow->assertNoEvents();
9620}
9621
9622TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9623 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9624 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009625 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9626 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009627 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009628 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9629 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009630 mDispatcher->onWindowInfosChanged(
9631 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009632
9633 touch();
9634
9635 mTouchWindow->assertNoEvents();
9636}
9637
9638TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9639 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9640 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009641 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9642 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009643 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009644 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9645 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009646 mDispatcher->onWindowInfosChanged(
9647 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009648
9649 touch();
9650
9651 mTouchWindow->consumeAnyMotionDown();
9652}
9653
9654TEST_F(InputDispatcherUntrustedTouchesTest,
9655 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9656 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009657 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9658 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009659 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009660 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9661 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009662 mDispatcher->onWindowInfosChanged(
9663 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009664
9665 touch();
9666
9667 mTouchWindow->consumeAnyMotionDown();
9668}
9669
9670TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9671 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009672 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9673 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009674 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009675 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9676 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009677 mDispatcher->onWindowInfosChanged(
9678 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009679
9680 touch();
9681
9682 mTouchWindow->assertNoEvents();
9683}
9684
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009685TEST_F(InputDispatcherUntrustedTouchesTest,
9686 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9687 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009688 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9689 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009690 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009691 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9692 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009693 mDispatcher->onWindowInfosChanged(
9694 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009695
9696 touch();
9697
9698 mTouchWindow->assertNoEvents();
9699}
9700
9701TEST_F(InputDispatcherUntrustedTouchesTest,
9702 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9703 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009704 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9705 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009706 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009707 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9708 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009709 mDispatcher->onWindowInfosChanged(
9710 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009711
9712 touch();
9713
9714 mTouchWindow->consumeAnyMotionDown();
9715}
9716
9717TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9718 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009719 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9720 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009721 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009722
9723 touch();
9724
9725 mTouchWindow->consumeAnyMotionDown();
9726}
9727
9728TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9729 const sp<FakeWindowHandle>& w =
9730 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009731 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009732
9733 touch();
9734
9735 mTouchWindow->consumeAnyMotionDown();
9736}
9737
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009738TEST_F(InputDispatcherUntrustedTouchesTest,
9739 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9740 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9741 const sp<FakeWindowHandle>& w =
9742 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009743 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009744
9745 touch();
9746
9747 mTouchWindow->assertNoEvents();
9748}
9749
9750TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9751 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9752 const sp<FakeWindowHandle>& w =
9753 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009754 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009755
9756 touch();
9757
9758 mTouchWindow->consumeAnyMotionDown();
9759}
9760
9761TEST_F(InputDispatcherUntrustedTouchesTest,
9762 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9763 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9764 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009765 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9766 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009767 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009768
9769 touch();
9770
9771 mTouchWindow->consumeAnyMotionDown();
9772}
9773
9774TEST_F(InputDispatcherUntrustedTouchesTest,
9775 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9776 const sp<FakeWindowHandle>& w1 =
9777 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9778 OPACITY_BELOW_THRESHOLD);
9779 const sp<FakeWindowHandle>& w2 =
9780 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9781 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009782 mDispatcher->onWindowInfosChanged(
9783 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009784
9785 touch();
9786
9787 mTouchWindow->assertNoEvents();
9788}
9789
9790/**
9791 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9792 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9793 * (which alone would result in allowing touches) does not affect the blocking behavior.
9794 */
9795TEST_F(InputDispatcherUntrustedTouchesTest,
9796 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9797 const sp<FakeWindowHandle>& wB =
9798 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9799 OPACITY_BELOW_THRESHOLD);
9800 const sp<FakeWindowHandle>& wC =
9801 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9802 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009803 mDispatcher->onWindowInfosChanged(
9804 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009805
9806 touch();
9807
9808 mTouchWindow->assertNoEvents();
9809}
9810
9811/**
9812 * This test is testing that a window from a different UID but with same application token doesn't
9813 * block the touch. Apps can share the application token for close UI collaboration for example.
9814 */
9815TEST_F(InputDispatcherUntrustedTouchesTest,
9816 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9817 const sp<FakeWindowHandle>& w =
9818 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9819 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009820 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009821
9822 touch();
9823
9824 mTouchWindow->consumeAnyMotionDown();
9825}
9826
arthurhungb89ccb02020-12-30 16:19:01 +08009827class InputDispatcherDragTests : public InputDispatcherTest {
9828protected:
9829 std::shared_ptr<FakeApplicationHandle> mApp;
9830 sp<FakeWindowHandle> mWindow;
9831 sp<FakeWindowHandle> mSecondWindow;
9832 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009833 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009834 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9835 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009836
9837 void SetUp() override {
9838 InputDispatcherTest::SetUp();
9839 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009840 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009841 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009842
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009843 mSecondWindow =
9844 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009845 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009846
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009847 mSpyWindow =
9848 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009849 mSpyWindow->setSpy(true);
9850 mSpyWindow->setTrustedOverlay(true);
9851 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9852
arthurhungb89ccb02020-12-30 16:19:01 +08009853 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009854 mDispatcher->onWindowInfosChanged(
9855 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9856 {},
9857 0,
9858 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009859 }
9860
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009861 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9862 switch (fromSource) {
9863 case AINPUT_SOURCE_TOUCHSCREEN:
9864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009865 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009866 ADISPLAY_ID_DEFAULT, {50, 50}))
9867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9868 break;
9869 case AINPUT_SOURCE_STYLUS:
9870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009871 injectMotionEvent(*mDispatcher,
9872 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9873 AINPUT_SOURCE_STYLUS)
9874 .buttonState(
9875 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9876 .pointer(PointerBuilder(0, ToolType::STYLUS)
9877 .x(50)
9878 .y(50))
9879 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009880 break;
9881 case AINPUT_SOURCE_MOUSE:
9882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009883 injectMotionEvent(*mDispatcher,
9884 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9885 AINPUT_SOURCE_MOUSE)
9886 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9887 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9888 ToolType::MOUSE)
9889 .x(50)
9890 .y(50))
9891 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009892 break;
9893 default:
9894 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9895 }
arthurhungb89ccb02020-12-30 16:19:01 +08009896
9897 // Window should receive motion event.
9898 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009899 // Spy window should also receive motion event
9900 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009901 }
9902
9903 // Start performing drag, we will create a drag window and transfer touch to it.
9904 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9905 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009906 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009907 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009908 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009909 }
arthurhungb89ccb02020-12-30 16:19:01 +08009910
9911 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009912 mDragWindow =
9913 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009914 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009915 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9916 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9917 {},
9918 0,
9919 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009920
9921 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009922 bool transferred =
9923 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009924 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009925 if (transferred) {
9926 mWindow->consumeMotionCancel();
9927 mDragWindow->consumeMotionDown();
9928 }
9929 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009930 }
9931};
9932
9933TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009934 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009935
9936 // Move on window.
9937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009938 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009939 ADISPLAY_ID_DEFAULT, {50, 50}))
9940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9941 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9942 mWindow->consumeDragEvent(false, 50, 50);
9943 mSecondWindow->assertNoEvents();
9944
9945 // Move to another window.
9946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009948 ADISPLAY_ID_DEFAULT, {150, 50}))
9949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9950 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9951 mWindow->consumeDragEvent(true, 150, 50);
9952 mSecondWindow->consumeDragEvent(false, 50, 50);
9953
9954 // Move back to original window.
9955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009956 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009957 ADISPLAY_ID_DEFAULT, {50, 50}))
9958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9959 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9960 mWindow->consumeDragEvent(false, 50, 50);
9961 mSecondWindow->consumeDragEvent(true, -50, 50);
9962
9963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009964 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9965 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9967 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9968 mWindow->assertNoEvents();
9969 mSecondWindow->assertNoEvents();
9970}
9971
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009972TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009973 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009974
9975 // No cancel event after drag start
9976 mSpyWindow->assertNoEvents();
9977
9978 const MotionEvent secondFingerDownEvent =
9979 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9980 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009981 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9982 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009983 .build();
9984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009985 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009986 InputEventInjectionSync::WAIT_FOR_RESULT))
9987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9988
9989 // Receives cancel for first pointer after next pointer down
9990 mSpyWindow->consumeMotionCancel();
9991 mSpyWindow->consumeMotionDown();
9992
9993 mSpyWindow->assertNoEvents();
9994}
9995
arthurhungf452d0b2021-01-06 00:19:52 +08009996TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009997 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009998
9999 // Move on window.
10000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010001 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010002 ADISPLAY_ID_DEFAULT, {50, 50}))
10003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10004 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10005 mWindow->consumeDragEvent(false, 50, 50);
10006 mSecondWindow->assertNoEvents();
10007
10008 // Move to another window.
10009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010010 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010011 ADISPLAY_ID_DEFAULT, {150, 50}))
10012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10013 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10014 mWindow->consumeDragEvent(true, 150, 50);
10015 mSecondWindow->consumeDragEvent(false, 50, 50);
10016
10017 // drop to another window.
10018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010019 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010020 {150, 50}))
10021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10022 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010023 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010024 mWindow->assertNoEvents();
10025 mSecondWindow->assertNoEvents();
10026}
10027
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010028TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10029 startDrag();
10030
10031 // No cancel event after drag start
10032 mSpyWindow->assertNoEvents();
10033
10034 const MotionEvent secondFingerDownEvent =
10035 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10036 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10037 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10038 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10039 .build();
10040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10041 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10042 InputEventInjectionSync::WAIT_FOR_RESULT))
10043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10044
10045 // Receives cancel for first pointer after next pointer down
10046 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010047 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010048 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10049
10050 mSpyWindow->assertNoEvents();
10051
10052 // Spy window calls pilfer pointers
10053 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10054 mDragWindow->assertNoEvents();
10055
10056 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010057 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010058 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10059 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10060 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10061 .build();
10062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010063 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010064 InputEventInjectionSync::WAIT_FOR_RESULT))
10065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10066
10067 // Drag window should still receive the new event
10068 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10069 mDragWindow->assertNoEvents();
10070}
10071
arthurhung6d4bed92021-03-17 11:59:33 +080010072TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010073 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010074
10075 // Move on window and keep button pressed.
10076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010077 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010078 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10079 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010081 .build()))
10082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10083 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10084 mWindow->consumeDragEvent(false, 50, 50);
10085 mSecondWindow->assertNoEvents();
10086
10087 // Move to another window and release button, expect to drop item.
10088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010089 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010090 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10091 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010092 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010093 .build()))
10094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10095 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10096 mWindow->assertNoEvents();
10097 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010098 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010099
10100 // nothing to the window.
10101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010102 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010103 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10104 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010105 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010106 .build()))
10107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10108 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10109 mWindow->assertNoEvents();
10110 mSecondWindow->assertNoEvents();
10111}
10112
Arthur Hung54745652022-04-20 07:17:41 +000010113TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010114 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010115
10116 // Set second window invisible.
10117 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010118 mDispatcher->onWindowInfosChanged(
10119 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010120
10121 // Move on window.
10122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010123 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010124 ADISPLAY_ID_DEFAULT, {50, 50}))
10125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10126 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10127 mWindow->consumeDragEvent(false, 50, 50);
10128 mSecondWindow->assertNoEvents();
10129
10130 // Move to another window.
10131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010132 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010133 ADISPLAY_ID_DEFAULT, {150, 50}))
10134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10135 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10136 mWindow->consumeDragEvent(true, 150, 50);
10137 mSecondWindow->assertNoEvents();
10138
10139 // drop to another window.
10140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010141 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010142 {150, 50}))
10143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10144 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010145 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010146 mWindow->assertNoEvents();
10147 mSecondWindow->assertNoEvents();
10148}
10149
Arthur Hung54745652022-04-20 07:17:41 +000010150TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010151 // Ensure window could track pointerIds if it didn't support split touch.
10152 mWindow->setPreventSplitting(true);
10153
Arthur Hung54745652022-04-20 07:17:41 +000010154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010155 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010156 {50, 50}))
10157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10158 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10159
10160 const MotionEvent secondFingerDownEvent =
10161 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10162 .displayId(ADISPLAY_ID_DEFAULT)
10163 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010164 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10165 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010166 .build();
10167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010168 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010169 InputEventInjectionSync::WAIT_FOR_RESULT))
10170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010171 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010172
10173 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010174 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010175}
10176
10177TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10178 // First down on second window.
10179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010180 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010181 {150, 50}))
10182 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10183
10184 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10185
10186 // Second down on first window.
10187 const MotionEvent secondFingerDownEvent =
10188 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10189 .displayId(ADISPLAY_ID_DEFAULT)
10190 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010191 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10192 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010193 .build();
10194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010195 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010196 InputEventInjectionSync::WAIT_FOR_RESULT))
10197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10198 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10199
10200 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010201 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010202
10203 // Move on window.
10204 const MotionEvent secondFingerMoveEvent =
10205 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10206 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010207 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10208 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010209 .build();
10210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010211 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010212 InputEventInjectionSync::WAIT_FOR_RESULT));
10213 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10214 mWindow->consumeDragEvent(false, 50, 50);
10215 mSecondWindow->consumeMotionMove();
10216
10217 // Release the drag pointer should perform drop.
10218 const MotionEvent secondFingerUpEvent =
10219 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10220 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010221 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10222 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010223 .build();
10224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010225 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010226 InputEventInjectionSync::WAIT_FOR_RESULT));
10227 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010228 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010229 mWindow->assertNoEvents();
10230 mSecondWindow->consumeMotionMove();
10231}
10232
Arthur Hung3915c1f2022-05-31 07:17:17 +000010233TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010234 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010235
10236 // Update window of second display.
10237 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010238 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010239 mDispatcher->onWindowInfosChanged(
10240 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10241 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10242 {},
10243 0,
10244 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010245
10246 // Let second display has a touch state.
10247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010248 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010249 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10250 AINPUT_SOURCE_TOUCHSCREEN)
10251 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010252 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010253 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010254 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010255 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010256 mDispatcher->onWindowInfosChanged(
10257 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10258 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10259 {},
10260 0,
10261 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010262
10263 // Move on window.
10264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010265 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010266 ADISPLAY_ID_DEFAULT, {50, 50}))
10267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10268 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10269 mWindow->consumeDragEvent(false, 50, 50);
10270 mSecondWindow->assertNoEvents();
10271
10272 // Move to another window.
10273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010274 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010275 ADISPLAY_ID_DEFAULT, {150, 50}))
10276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10277 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10278 mWindow->consumeDragEvent(true, 150, 50);
10279 mSecondWindow->consumeDragEvent(false, 50, 50);
10280
10281 // drop to another window.
10282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010283 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010284 {150, 50}))
10285 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10286 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010287 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010288 mWindow->assertNoEvents();
10289 mSecondWindow->assertNoEvents();
10290}
10291
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010292TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10293 startDrag(true, AINPUT_SOURCE_MOUSE);
10294 // Move on window.
10295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010296 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010297 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10298 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010299 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010300 .x(50)
10301 .y(50))
10302 .build()))
10303 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10304 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10305 mWindow->consumeDragEvent(false, 50, 50);
10306 mSecondWindow->assertNoEvents();
10307
10308 // Move to another window.
10309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010310 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010311 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10312 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010313 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010314 .x(150)
10315 .y(50))
10316 .build()))
10317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10318 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10319 mWindow->consumeDragEvent(true, 150, 50);
10320 mSecondWindow->consumeDragEvent(false, 50, 50);
10321
10322 // drop to another window.
10323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010324 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010325 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10326 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010327 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010328 .x(150)
10329 .y(50))
10330 .build()))
10331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10332 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010333 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010334 mWindow->assertNoEvents();
10335 mSecondWindow->assertNoEvents();
10336}
10337
Linnan Li5af92f92023-07-14 14:36:22 +080010338/**
10339 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10340 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10341 */
10342TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10343 // Down on second window
10344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10345 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10346 {150, 50}))
10347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10348
10349 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10350 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10351
10352 // Down on first window
10353 const MotionEvent secondFingerDownEvent =
10354 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10355 .displayId(ADISPLAY_ID_DEFAULT)
10356 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10357 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10358 .build();
10359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10360 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10361 InputEventInjectionSync::WAIT_FOR_RESULT))
10362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10363 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10364 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10365 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10366
10367 // Start drag on first window
10368 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10369
10370 // Trigger cancel
10371 mDispatcher->cancelCurrentTouch();
10372 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10373 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10374 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10375
10376 ASSERT_TRUE(mDispatcher->waitForIdle());
10377 // The D&D finished with nullptr
10378 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10379
10380 // Remove drag window
10381 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10382
10383 // Inject a simple gesture, ensure dispatcher not crashed
10384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10385 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10386 PointF{50, 50}))
10387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10388 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10389
10390 const MotionEvent moveEvent =
10391 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10392 .displayId(ADISPLAY_ID_DEFAULT)
10393 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10394 .build();
10395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10396 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10397 InputEventInjectionSync::WAIT_FOR_RESULT))
10398 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10399 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10400
10401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10402 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10403 {50, 50}))
10404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10405 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10406}
10407
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010408TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10409 // Start hovering over the window.
10410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10411 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10412 ADISPLAY_ID_DEFAULT, {50, 50}));
10413
10414 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10415 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10416
10417 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10418 << "Drag and drop should not work with a hovering pointer";
10419}
10420
Vishnu Nair062a8672021-09-03 16:07:44 -070010421class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10422
10423TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010425 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10426 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010427 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010428 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10429 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010431 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010432 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010433
10434 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010435 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010436 window->assertNoEvents();
10437
Prabir Pradhan678438e2023-04-13 19:32:51 +000010438 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10439 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010440 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10441 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010442 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010443 window->assertNoEvents();
10444
10445 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010446 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010448
Prabir Pradhan678438e2023-04-13 19:32:51 +000010449 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010450 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10451
Prabir Pradhan678438e2023-04-13 19:32:51 +000010452 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10453 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010454 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10455 window->assertNoEvents();
10456}
10457
10458TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10459 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10460 std::make_shared<FakeApplicationHandle>();
10461 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010462 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10463 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010464 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010465 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010466 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010468 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10469 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010470 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010471 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010472 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10473 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010474 mDispatcher->onWindowInfosChanged(
10475 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010476 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010477 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010478
10479 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010480 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010481 window->assertNoEvents();
10482
Prabir Pradhan678438e2023-04-13 19:32:51 +000010483 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10484 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010485 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10486 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010487 window->assertNoEvents();
10488
10489 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010490 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010491 mDispatcher->onWindowInfosChanged(
10492 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010493
Prabir Pradhan678438e2023-04-13 19:32:51 +000010494 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010495 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10496
Prabir Pradhan678438e2023-04-13 19:32:51 +000010497 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10498 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010499 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10500 window->assertNoEvents();
10501}
10502
10503TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10504 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10505 std::make_shared<FakeApplicationHandle>();
10506 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010507 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10508 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010509 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010510 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010511 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10514 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010515 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010516 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010517 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10518 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010519 mDispatcher->onWindowInfosChanged(
10520 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010521 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010522 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010523
10524 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010525 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010526 window->assertNoEvents();
10527
Prabir Pradhan678438e2023-04-13 19:32:51 +000010528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10531 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010532 window->assertNoEvents();
10533
10534 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010535 mDispatcher->onWindowInfosChanged(
10536 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010537
Prabir Pradhan678438e2023-04-13 19:32:51 +000010538 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010539 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10540
Prabir Pradhan678438e2023-04-13 19:32:51 +000010541 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10542 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010543 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10544 window->assertNoEvents();
10545}
10546
Antonio Kantekf16f2832021-09-28 04:39:20 +000010547class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10548protected:
10549 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010550 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010551 sp<FakeWindowHandle> mWindow;
10552 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010553 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010554
10555 void SetUp() override {
10556 InputDispatcherTest::SetUp();
10557
10558 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010559 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010560 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010561 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010562 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010563 mSecondWindow =
10564 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010565 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010566 mThirdWindow =
10567 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10568 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10569 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010570
10571 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010572 mDispatcher->onWindowInfosChanged(
10573 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10574 {},
10575 0,
10576 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010577 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010578 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010579
Antonio Kantek15beb512022-06-13 22:35:41 +000010580 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010581 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010582 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010583 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10584 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010585 mThirdWindow->assertNoEvents();
10586 }
10587
10588 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10589 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010590 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010591 SECOND_DISPLAY_ID)) {
10592 mWindow->assertNoEvents();
10593 mSecondWindow->assertNoEvents();
10594 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010595 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010596 }
10597
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010598 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010599 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010600 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10601 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010602 mWindow->consumeTouchModeEvent(inTouchMode);
10603 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010604 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010605 }
10606};
10607
Antonio Kantek26defcf2022-02-08 01:12:27 +000010608TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010609 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010610 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10611 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010612 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010613}
10614
Antonio Kantek26defcf2022-02-08 01:12:27 +000010615TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10616 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010617 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010618 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010619 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010620 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010621 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010622 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010623 mWindow->assertNoEvents();
10624 mSecondWindow->assertNoEvents();
10625}
10626
10627TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10628 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010629 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010630 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010631 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010632 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010633 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010634}
10635
Antonio Kantekf16f2832021-09-28 04:39:20 +000010636TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010637 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010638 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10639 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010640 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010641 mWindow->assertNoEvents();
10642 mSecondWindow->assertNoEvents();
10643}
10644
Antonio Kantek15beb512022-06-13 22:35:41 +000010645TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10646 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10647 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10648 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010649 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010650 mWindow->assertNoEvents();
10651 mSecondWindow->assertNoEvents();
10652 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10653}
10654
Antonio Kantek48710e42022-03-24 14:19:30 -070010655TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10656 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10658 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010659 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10660 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10661
10662 // Then remove focus.
10663 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010664 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010665
10666 // Assert that caller can switch touch mode by owning one of the last interacted window.
10667 const WindowInfo& windowInfo = *mWindow->getInfo();
10668 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10669 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010670 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010671}
10672
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010673class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10674public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010675 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010676 std::shared_ptr<FakeApplicationHandle> application =
10677 std::make_shared<FakeApplicationHandle>();
10678 std::string name = "Fake Spy ";
10679 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010680 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10681 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010682 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010683 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010684 return spy;
10685 }
10686
10687 sp<FakeWindowHandle> createForeground() {
10688 std::shared_ptr<FakeApplicationHandle> application =
10689 std::make_shared<FakeApplicationHandle>();
10690 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010691 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10692 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010693 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010694 return window;
10695 }
10696
10697private:
10698 int mSpyCount{0};
10699};
10700
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010701using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010702/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010703 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10704 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010705TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010706 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010707 ScopedSilentDeath _silentDeath;
10708
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010709 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010710 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010711 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010712 ".* not a trusted overlay");
10713}
10714
10715/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010716 * Input injection into a display with a spy window but no foreground windows should succeed.
10717 */
10718TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010719 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010720 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010721
10722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010723 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10725 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10726}
10727
10728/**
10729 * Verify the order in which different input windows receive events. The touched foreground window
10730 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10731 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10732 * receive events before ones belows it.
10733 *
10734 * Here, we set up a scenario with four windows in the following Z order from the top:
10735 * spy1, spy2, window, spy3.
10736 * We then inject an event and verify that the foreground "window" receives it first, followed by
10737 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10738 * window.
10739 */
10740TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10741 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010742 auto spy1 = createSpy();
10743 auto spy2 = createSpy();
10744 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010745 mDispatcher->onWindowInfosChanged(
10746 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010747 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10748 const size_t numChannels = channels.size();
10749
Michael Wright8e9a8562022-02-09 13:44:29 +000010750 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010751 if (!epollFd.ok()) {
10752 FAIL() << "Failed to create epoll fd";
10753 }
10754
10755 for (size_t i = 0; i < numChannels; i++) {
10756 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10757 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10758 FAIL() << "Failed to add fd to epoll";
10759 }
10760 }
10761
10762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10765
10766 std::vector<size_t> eventOrder;
10767 std::vector<struct epoll_event> events(numChannels);
10768 for (;;) {
10769 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10770 (100ms).count());
10771 if (nFds < 0) {
10772 FAIL() << "Failed to call epoll_wait";
10773 }
10774 if (nFds == 0) {
10775 break; // epoll_wait timed out
10776 }
10777 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010778 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010779 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010780 channels[i]->consumeMotionDown();
10781 }
10782 }
10783
10784 // Verify the order in which the events were received.
10785 EXPECT_EQ(3u, eventOrder.size());
10786 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10787 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10788 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10789}
10790
10791/**
10792 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10793 */
10794TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10795 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010796 auto spy = createSpy();
10797 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010798 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010799
10800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10803 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10804 spy->assertNoEvents();
10805}
10806
10807/**
10808 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10809 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10810 * to the window.
10811 */
10812TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10813 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010814 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010815 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010816 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010817
10818 // Inject an event outside the spy window's touchable region.
10819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010820 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10822 window->consumeMotionDown();
10823 spy->assertNoEvents();
10824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010825 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10827 window->consumeMotionUp();
10828 spy->assertNoEvents();
10829
10830 // Inject an event inside the spy window's touchable region.
10831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010832 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010833 {5, 10}))
10834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10835 window->consumeMotionDown();
10836 spy->consumeMotionDown();
10837}
10838
10839/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010840 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010841 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010842 */
10843TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10844 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010845 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010846 auto spy = createSpy();
10847 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010848 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010849 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010850 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010851
10852 // Inject an event outside the spy window's frame and touchable region.
10853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010854 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010855 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10857 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010858 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010859}
10860
10861/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010862 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10863 * pointers that are down within its bounds.
10864 */
10865TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10866 auto windowLeft = createForeground();
10867 windowLeft->setFrame({0, 0, 100, 200});
10868 auto windowRight = createForeground();
10869 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010870 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010871 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010872 mDispatcher->onWindowInfosChanged(
10873 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010874
10875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010877 {50, 50}))
10878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10879 windowLeft->consumeMotionDown();
10880 spy->consumeMotionDown();
10881
10882 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010883 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010884 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010885 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10886 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010887 .build();
10888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010889 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010890 InputEventInjectionSync::WAIT_FOR_RESULT))
10891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10892 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010893 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010894}
10895
10896/**
10897 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10898 * the spy should receive the second pointer with ACTION_DOWN.
10899 */
10900TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10901 auto window = createForeground();
10902 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010903 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010904 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010905 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010906
10907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010908 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010909 {50, 50}))
10910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10911 window->consumeMotionDown();
10912 spyRight->assertNoEvents();
10913
10914 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010915 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010916 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010917 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10918 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010919 .build();
10920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010921 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010922 InputEventInjectionSync::WAIT_FOR_RESULT))
10923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010924 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010925 spyRight->consumeMotionDown();
10926}
10927
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010928/**
10929 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10930 * windows should be allowed to control split touch.
10931 */
10932TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010933 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010934 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010935 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010936 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010937
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010938 auto window = createForeground();
10939 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010940
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010941 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010942
10943 // First finger down, no window touched.
10944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010945 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010946 {100, 200}))
10947 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10948 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10949 window->assertNoEvents();
10950
10951 // Second finger down on window, the window should receive touch down.
10952 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010953 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010954 .displayId(ADISPLAY_ID_DEFAULT)
10955 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010956 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10957 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010958 .build();
10959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010960 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010961 InputEventInjectionSync::WAIT_FOR_RESULT))
10962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10963
10964 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010965 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010966}
10967
10968/**
10969 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10970 * do not receive key events.
10971 */
10972TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010973 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010974 spy->setFocusable(false);
10975
10976 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010977 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010978 setFocusedWindow(window);
10979 window->consumeFocusEvent(true);
10980
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010982 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10983 window->consumeKeyDown(ADISPLAY_ID_NONE);
10984
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010986 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10987 window->consumeKeyUp(ADISPLAY_ID_NONE);
10988
10989 spy->assertNoEvents();
10990}
10991
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010992using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10993
10994/**
10995 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10996 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10997 */
10998TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10999 auto window = createForeground();
11000 auto spy1 = createSpy();
11001 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011002 mDispatcher->onWindowInfosChanged(
11003 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011004
11005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011006 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11008 window->consumeMotionDown();
11009 spy1->consumeMotionDown();
11010 spy2->consumeMotionDown();
11011
11012 // Pilfer pointers from the second spy window.
11013 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11014 spy2->assertNoEvents();
11015 spy1->consumeMotionCancel();
11016 window->consumeMotionCancel();
11017
11018 // The rest of the gesture should only be sent to the second spy window.
11019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011020 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011021 ADISPLAY_ID_DEFAULT))
11022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11023 spy2->consumeMotionMove();
11024 spy1->assertNoEvents();
11025 window->assertNoEvents();
11026}
11027
11028/**
11029 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11030 * in the middle of the gesture.
11031 */
11032TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11033 auto window = createForeground();
11034 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011035 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011036
11037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11040 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11041 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11042
11043 window->releaseChannel();
11044
11045 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11046
11047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011048 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011049 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11050 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11051}
11052
11053/**
11054 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11055 * the spy, but not to any other windows.
11056 */
11057TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11058 auto spy = createSpy();
11059 auto window = createForeground();
11060
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011061 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011062
11063 // First finger down on the window and the spy.
11064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011065 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011066 {100, 200}))
11067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11068 spy->consumeMotionDown();
11069 window->consumeMotionDown();
11070
11071 // Spy window pilfers the pointers.
11072 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11073 window->consumeMotionCancel();
11074
11075 // Second finger down on the window and spy, but the window should not receive the pointer down.
11076 const MotionEvent secondFingerDownEvent =
11077 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11078 .displayId(ADISPLAY_ID_DEFAULT)
11079 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011080 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11081 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011082 .build();
11083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011084 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011085 InputEventInjectionSync::WAIT_FOR_RESULT))
11086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11087
Harry Cutts33476232023-01-30 19:57:29 +000011088 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011089
11090 // Third finger goes down outside all windows, so injection should fail.
11091 const MotionEvent thirdFingerDownEvent =
11092 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11093 .displayId(ADISPLAY_ID_DEFAULT)
11094 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011095 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11096 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11097 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011098 .build();
11099 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011100 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011101 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011102 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011103
11104 spy->assertNoEvents();
11105 window->assertNoEvents();
11106}
11107
11108/**
11109 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11110 */
11111TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11112 auto spy = createSpy();
11113 spy->setFrame(Rect(0, 0, 100, 100));
11114 auto window = createForeground();
11115 window->setFrame(Rect(0, 0, 200, 200));
11116
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011117 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011118
11119 // First finger down on the window only
11120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011121 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011122 {150, 150}))
11123 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11124 window->consumeMotionDown();
11125
11126 // Second finger down on the spy and window
11127 const MotionEvent secondFingerDownEvent =
11128 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11129 .displayId(ADISPLAY_ID_DEFAULT)
11130 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011131 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11132 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011133 .build();
11134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011135 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011136 InputEventInjectionSync::WAIT_FOR_RESULT))
11137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11138 spy->consumeMotionDown();
11139 window->consumeMotionPointerDown(1);
11140
11141 // Third finger down on the spy and window
11142 const MotionEvent thirdFingerDownEvent =
11143 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11144 .displayId(ADISPLAY_ID_DEFAULT)
11145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11148 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011149 .build();
11150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011151 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011152 InputEventInjectionSync::WAIT_FOR_RESULT))
11153 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11154 spy->consumeMotionPointerDown(1);
11155 window->consumeMotionPointerDown(2);
11156
11157 // Spy window pilfers the pointers.
11158 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011159 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11160 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011161
11162 spy->assertNoEvents();
11163 window->assertNoEvents();
11164}
11165
11166/**
11167 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11168 * other windows should be canceled. If this results in the cancellation of all pointers for some
11169 * window, then that window should receive ACTION_CANCEL.
11170 */
11171TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11172 auto spy = createSpy();
11173 spy->setFrame(Rect(0, 0, 100, 100));
11174 auto window = createForeground();
11175 window->setFrame(Rect(0, 0, 200, 200));
11176
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011177 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011178
11179 // First finger down on both spy and window
11180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011181 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011182 {10, 10}))
11183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11184 window->consumeMotionDown();
11185 spy->consumeMotionDown();
11186
11187 // Second finger down on the spy and window
11188 const MotionEvent secondFingerDownEvent =
11189 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11190 .displayId(ADISPLAY_ID_DEFAULT)
11191 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011192 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11193 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011194 .build();
11195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011196 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011197 InputEventInjectionSync::WAIT_FOR_RESULT))
11198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11199 spy->consumeMotionPointerDown(1);
11200 window->consumeMotionPointerDown(1);
11201
11202 // Spy window pilfers the pointers.
11203 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11204 window->consumeMotionCancel();
11205
11206 spy->assertNoEvents();
11207 window->assertNoEvents();
11208}
11209
11210/**
11211 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11212 * be sent to other windows
11213 */
11214TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11215 auto spy = createSpy();
11216 spy->setFrame(Rect(0, 0, 100, 100));
11217 auto window = createForeground();
11218 window->setFrame(Rect(0, 0, 200, 200));
11219
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011220 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011221
11222 // First finger down on both window and spy
11223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011225 {10, 10}))
11226 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11227 window->consumeMotionDown();
11228 spy->consumeMotionDown();
11229
11230 // Spy window pilfers the pointers.
11231 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11232 window->consumeMotionCancel();
11233
11234 // Second finger down on the window only
11235 const MotionEvent secondFingerDownEvent =
11236 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11237 .displayId(ADISPLAY_ID_DEFAULT)
11238 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011239 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11240 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011241 .build();
11242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011243 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011244 InputEventInjectionSync::WAIT_FOR_RESULT))
11245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11246 window->consumeMotionDown();
11247 window->assertNoEvents();
11248
11249 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11250 spy->consumeMotionMove();
11251 spy->assertNoEvents();
11252}
11253
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011254/**
11255 * A window on the left and a window on the right. Also, a spy window that's above all of the
11256 * windows, and spanning both left and right windows.
11257 * Send simultaneous motion streams from two different devices, one to the left window, and another
11258 * to the right window.
11259 * Pilfer from spy window.
11260 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11261 */
11262TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11263 sp<FakeWindowHandle> spy = createSpy();
11264 spy->setFrame(Rect(0, 0, 200, 200));
11265 sp<FakeWindowHandle> leftWindow = createForeground();
11266 leftWindow->setFrame(Rect(0, 0, 100, 100));
11267
11268 sp<FakeWindowHandle> rightWindow = createForeground();
11269 rightWindow->setFrame(Rect(100, 0, 200, 100));
11270
11271 constexpr int32_t stylusDeviceId = 1;
11272 constexpr int32_t touchDeviceId = 2;
11273
11274 mDispatcher->onWindowInfosChanged(
11275 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11276
11277 // Stylus down on left window and spy
11278 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11279 .deviceId(stylusDeviceId)
11280 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11281 .build());
11282 leftWindow->consumeMotionEvent(
11283 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11284 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11285
11286 // Finger down on right window and spy - but spy already has stylus
11287 mDispatcher->notifyMotion(
11288 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11289 .deviceId(touchDeviceId)
11290 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11291 .build());
11292 rightWindow->consumeMotionEvent(
11293 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011294 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011295
11296 // Act: pilfer from spy. Spy is currently receiving touch events.
11297 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011298 leftWindow->consumeMotionEvent(
11299 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011300 rightWindow->consumeMotionEvent(
11301 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11302
11303 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11304 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11305 .deviceId(stylusDeviceId)
11306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11307 .build());
11308 mDispatcher->notifyMotion(
11309 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11310 .deviceId(touchDeviceId)
11311 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11312 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011313 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011314
11315 spy->assertNoEvents();
11316 leftWindow->assertNoEvents();
11317 rightWindow->assertNoEvents();
11318}
11319
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011320TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11321 auto window = createForeground();
11322 auto spy = createSpy();
11323 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11324
11325 mDispatcher->notifyMotion(
11326 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11327 .deviceId(1)
11328 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11329 .build());
11330 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11331 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11332
11333 // Pilfer pointers from the spy window should fail.
11334 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11335 spy->assertNoEvents();
11336 window->assertNoEvents();
11337}
11338
Prabir Pradhand65552b2021-10-07 11:23:50 -070011339class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11340public:
11341 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11342 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11343 std::make_shared<FakeApplicationHandle>();
11344 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011345 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11346 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011347 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011348 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011349 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011350 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011351 overlay->setTrustedOverlay(true);
11352
11353 std::shared_ptr<FakeApplicationHandle> application =
11354 std::make_shared<FakeApplicationHandle>();
11355 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011356 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11357 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011358 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011359 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011360
11361 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011362 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011363 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011364 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011365 return {std::move(overlay), std::move(window)};
11366 }
11367
11368 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011369 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011370 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011371 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011372 }
11373
11374 void sendStylusEvent(int32_t action) {
11375 NotifyMotionArgs motionArgs =
11376 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11377 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011378 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011379 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011380 }
11381};
11382
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011383using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11384
11385TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011386 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011387 ScopedSilentDeath _silentDeath;
11388
Prabir Pradhand65552b2021-10-07 11:23:50 -070011389 auto [overlay, window] = setupStylusOverlayScenario();
11390 overlay->setTrustedOverlay(false);
11391 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011392 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11393 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011394 ".* not a trusted overlay");
11395}
11396
11397TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11398 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011399 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011400
11401 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11402 overlay->consumeMotionDown();
11403 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11404 overlay->consumeMotionUp();
11405
11406 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11407 window->consumeMotionDown();
11408 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11409 window->consumeMotionUp();
11410
11411 overlay->assertNoEvents();
11412 window->assertNoEvents();
11413}
11414
11415TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11416 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011417 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011418 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011419
11420 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11421 overlay->consumeMotionDown();
11422 window->consumeMotionDown();
11423 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11424 overlay->consumeMotionUp();
11425 window->consumeMotionUp();
11426
11427 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11428 window->consumeMotionDown();
11429 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11430 window->consumeMotionUp();
11431
11432 overlay->assertNoEvents();
11433 window->assertNoEvents();
11434}
11435
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011436/**
11437 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11438 * The scenario is as follows:
11439 * - The stylus interceptor overlay is configured as a spy window.
11440 * - The stylus interceptor spy receives the start of a new stylus gesture.
11441 * - It pilfers pointers and then configures itself to no longer be a spy.
11442 * - The stylus interceptor continues to receive the rest of the gesture.
11443 */
11444TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11445 auto [overlay, window] = setupStylusOverlayScenario();
11446 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011447 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011448
11449 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11450 overlay->consumeMotionDown();
11451 window->consumeMotionDown();
11452
11453 // The interceptor pilfers the pointers.
11454 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11455 window->consumeMotionCancel();
11456
11457 // The interceptor configures itself so that it is no longer a spy.
11458 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011459 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011460
11461 // It continues to receive the rest of the stylus gesture.
11462 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11463 overlay->consumeMotionMove();
11464 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11465 overlay->consumeMotionUp();
11466
11467 window->assertNoEvents();
11468}
11469
Prabir Pradhan5735a322022-04-11 17:23:34 +000011470struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011471 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011472 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011473 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11474 std::unique_ptr<InputDispatcher>& mDispatcher;
11475
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011476 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011477 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11478
11479 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011480 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011481 ADISPLAY_ID_DEFAULT, {100, 200},
11482 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11483 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11484 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11485 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11486 }
11487
11488 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011489 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011490 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011491 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011492 mPolicyFlags);
11493 }
11494
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011495 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011496 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11497 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011498 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11499 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011500 window->setOwnerInfo(mPid, mUid);
11501 return window;
11502 }
11503};
11504
11505using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11506
11507TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011508 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011509 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011511
11512 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11513 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11514 window->consumeMotionDown();
11515
11516 setFocusedWindow(window);
11517 window->consumeFocusEvent(true);
11518
11519 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11520 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11521 window->consumeKeyDown(ADISPLAY_ID_NONE);
11522}
11523
11524TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011525 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011526 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
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});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011530 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11531 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11532
11533 setFocusedWindow(window);
11534 window->consumeFocusEvent(true);
11535
11536 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11537 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11538 window->assertNoEvents();
11539}
11540
11541TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011542 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011543 auto window = owner.createWindow("Owned window");
11544 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011545 spy->setSpy(true);
11546 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011547 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011548
11549 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11550 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11551 spy->consumeMotionDown();
11552 window->consumeMotionDown();
11553}
11554
11555TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011556 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011557 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011558
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011559 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011560 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011561 randosSpy->setSpy(true);
11562 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011563 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011564
11565 // The event is targeted at owner's window, so injection should succeed, but the spy should
11566 // not receive the event.
11567 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11568 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11569 randosSpy->assertNoEvents();
11570 window->consumeMotionDown();
11571}
11572
11573TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011574 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011575 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011576
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011577 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011578 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011579 randosSpy->setSpy(true);
11580 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011581 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011582
11583 // A user that has injection permission can inject into any window.
11584 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011585 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011586 ADISPLAY_ID_DEFAULT));
11587 randosSpy->consumeMotionDown();
11588 window->consumeMotionDown();
11589
11590 setFocusedWindow(randosSpy);
11591 randosSpy->consumeFocusEvent(true);
11592
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011593 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011594 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11595 window->assertNoEvents();
11596}
11597
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011598TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011599 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011600 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011601
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011602 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011603 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011604 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11605 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011606 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011607
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011608 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011609 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11610 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11611 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011612 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011613}
11614
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011615using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11616
11617TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11619
11620 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11621 ADISPLAY_ID_DEFAULT);
11622 left->setFrame(Rect(0, 0, 100, 100));
11623 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11624 "Right Window", ADISPLAY_ID_DEFAULT);
11625 right->setFrame(Rect(100, 0, 200, 100));
11626 sp<FakeWindowHandle> spy =
11627 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11628 spy->setFrame(Rect(0, 0, 200, 100));
11629 spy->setTrustedOverlay(true);
11630 spy->setSpy(true);
11631
11632 mDispatcher->onWindowInfosChanged(
11633 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11634
11635 // Hover into the left window.
11636 mDispatcher->notifyMotion(
11637 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11638 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11639 .build());
11640
11641 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11642 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11643
11644 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11645 /*pointerId=*/0));
11646 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11647 /*pointerId=*/0));
11648 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11649 /*pointerId=*/0));
11650
11651 // Hover move to the right window.
11652 mDispatcher->notifyMotion(
11653 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11654 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11655 .build());
11656
11657 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11658 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11659 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11660
11661 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11662 /*pointerId=*/0));
11663 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11664 /*pointerId=*/0));
11665 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11666 /*pointerId=*/0));
11667
11668 // Stop hovering.
11669 mDispatcher->notifyMotion(
11670 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11671 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11672 .build());
11673
11674 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11675 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11676
11677 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11678 /*pointerId=*/0));
11679 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11680 /*pointerId=*/0));
11681 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11682 /*pointerId=*/0));
11683}
11684
11685TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11687
11688 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11689 ADISPLAY_ID_DEFAULT);
11690 left->setFrame(Rect(0, 0, 100, 100));
11691 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11692 "Right Window", ADISPLAY_ID_DEFAULT);
11693 right->setFrame(Rect(100, 0, 200, 100));
11694 sp<FakeWindowHandle> spy =
11695 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11696 spy->setFrame(Rect(0, 0, 200, 100));
11697 spy->setTrustedOverlay(true);
11698 spy->setSpy(true);
11699
11700 mDispatcher->onWindowInfosChanged(
11701 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11702
11703 // First pointer down on left window.
11704 mDispatcher->notifyMotion(
11705 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11706 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11707 .build());
11708
11709 left->consumeMotionDown();
11710 spy->consumeMotionDown();
11711
11712 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11713 /*pointerId=*/0));
11714 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11715 /*pointerId=*/0));
11716 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11717 /*pointerId=*/0));
11718
11719 // Second pointer down on right window.
11720 mDispatcher->notifyMotion(
11721 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11722 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11723 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11724 .build());
11725
11726 left->consumeMotionMove();
11727 right->consumeMotionDown();
11728 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11729
11730 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11731 /*pointerId=*/0));
11732 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11733 /*pointerId=*/0));
11734 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11735 /*pointerId=*/0));
11736 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11737 /*pointerId=*/1));
11738 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11739 /*pointerId=*/1));
11740 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11741 /*pointerId=*/1));
11742
11743 // Second pointer up.
11744 mDispatcher->notifyMotion(
11745 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11746 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11747 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11748 .build());
11749
11750 left->consumeMotionMove();
11751 right->consumeMotionUp();
11752 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11753
11754 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11755 /*pointerId=*/0));
11756 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11757 /*pointerId=*/0));
11758 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11759 /*pointerId=*/0));
11760 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11761 /*pointerId=*/1));
11762 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11763 /*pointerId=*/1));
11764 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11765 /*pointerId=*/1));
11766
11767 // First pointer up.
11768 mDispatcher->notifyMotion(
11769 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11770 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11771 .build());
11772
11773 left->consumeMotionUp();
11774 spy->consumeMotionUp();
11775
11776 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11777 /*pointerId=*/0));
11778 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11779 /*pointerId=*/0));
11780 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11781 /*pointerId=*/0));
11782}
11783
11784TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11786
11787 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11788 ADISPLAY_ID_DEFAULT);
11789 left->setFrame(Rect(0, 0, 100, 100));
11790 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11791 "Right Window", ADISPLAY_ID_DEFAULT);
11792 right->setFrame(Rect(100, 0, 200, 100));
11793
11794 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11795
11796 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11797 /*pointerId=*/0));
11798 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11799 /*pointerId=*/0));
11800
11801 // Hover move into the window.
11802 mDispatcher->notifyMotion(
11803 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11804 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11805 .rawXCursorPosition(50)
11806 .rawYCursorPosition(50)
11807 .deviceId(DEVICE_ID)
11808 .build());
11809
11810 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11811
11812 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11813 /*pointerId=*/0));
11814
11815 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11816 mDispatcher->notifyMotion(
11817 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11818 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11819 .rawXCursorPosition(51)
11820 .rawYCursorPosition(50)
11821 .deviceId(SECOND_DEVICE_ID)
11822 .build());
11823
11824 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11825 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11826
11827 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11828 // a HOVER_EXIT from the first device.
11829 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11830 /*pointerId=*/0));
11831 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11832 SECOND_DEVICE_ID,
11833 /*pointerId=*/0));
11834
11835 // Move the mouse outside the window. Document the current behavior, where the window does not
11836 // receive HOVER_EXIT even though the mouse left the window.
11837 mDispatcher->notifyMotion(
11838 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11839 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11840 .rawXCursorPosition(150)
11841 .rawYCursorPosition(50)
11842 .deviceId(SECOND_DEVICE_ID)
11843 .build());
11844
11845 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11846 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11847 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11848 /*pointerId=*/0));
11849 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11850 SECOND_DEVICE_ID,
11851 /*pointerId=*/0));
11852}
11853
Garfield Tane84e6f92019-08-29 17:28:41 -070011854} // namespace android::inputdispatcher