blob: 93f926fea40d5d9cb1441d059c837503be85476f [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Harry Cutts33476232023-01-30 19:57:29 +0000575 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 }
577
Josep del Riob3981622023-04-18 15:49:45 +0000578 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
579 std::scoped_lock lock(mLock);
580 mPokedUserActivity = true;
581 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700583 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
584 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
585 }
586
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600587 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700588 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700589 mOnPointerDownToken = newToken;
590 }
591
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000592 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800593 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000594 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800595 mPointerCaptureChangedCondition.notify_all();
596 }
597
arthurhungf452d0b2021-01-06 00:19:52 +0800598 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
599 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800600 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800601 mDropTargetWindowToken = token;
602 }
603
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000604 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000605 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000606 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
607 }
608
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700609 void assertFilterInputEventWasCalledInternal(
610 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700611 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800612 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700613 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800614 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800615 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700617} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619// --- InputDispatcherTest ---
620
621class InputDispatcherTest : public testing::Test {
622protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000623 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700624 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000626 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000627 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700628 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
629
Harry Cutts101ee9b2023-07-06 18:04:14 +0000630 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000631 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700632 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 }
634
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000635 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700636 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000637 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700638 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800639 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700640
641 /**
642 * Used for debugging when writing the test
643 */
644 void dumpDispatcherState() {
645 std::string dump;
646 mDispatcher->dump(dump);
647 std::stringstream ss(dump);
648 std::string to;
649
650 while (std::getline(ss, to, '\n')) {
651 ALOGE("%s", to.c_str());
652 }
653 }
Vishnu Nair958da932020-08-21 17:12:37 -0700654
Chavi Weingarten847e8512023-03-29 00:26:09 +0000655 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700656 FocusRequest request;
657 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000658 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700659 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
660 request.displayId = window->getInfo()->displayId;
661 mDispatcher->setFocusedWindow(request);
662 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663};
664
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
666 KeyEvent event;
667
668 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800669 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
670 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000671 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600672 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000674 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000675 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676 << "Should reject key events with undefined action.";
677
678 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800679 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
680 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600681 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800682 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000683 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000684 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685 << "Should reject key events with ACTION_MULTIPLE.";
686}
687
688TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
689 MotionEvent event;
690 PointerProperties pointerProperties[MAX_POINTERS + 1];
691 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800692 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800693 pointerProperties[i].clear();
694 pointerProperties[i].id = i;
695 pointerCoords[i].clear();
696 }
697
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800698 // Some constants commonly used below
699 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
700 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
701 constexpr int32_t metaState = AMETA_NONE;
702 constexpr MotionClassification classification = MotionClassification::NONE;
703
chaviw9eaa22c2020-07-01 16:21:27 -0700704 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800706 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000707 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700708 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700709 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
710 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000711 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800712 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000713 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000714 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715 << "Should reject motion events with undefined action.";
716
717 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800719 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
720 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
721 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
722 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000723 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000725 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with pointer down index too large.";
728
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700730 AMOTION_EVENT_ACTION_POINTER_DOWN |
731 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700732 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
733 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700734 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000735 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000737 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with pointer down index too small.";
740
741 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800742 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800743 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
744 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
745 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
746 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000747 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800748 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000749 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000750 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800751 << "Should reject motion events with pointer up index too large.";
752
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700754 AMOTION_EVENT_ACTION_POINTER_UP |
755 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700756 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
757 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700758 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000759 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000761 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000762 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 << "Should reject motion events with pointer up index too small.";
764
765 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800766 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
767 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700768 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700769 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
770 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000771 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000773 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000774 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800775 << "Should reject motion events with 0 pointers.";
776
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000782 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with more than MAX_POINTERS pointers.";
787
788 // Rejects motion events with invalid pointer ids.
789 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800790 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
791 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700792 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700793 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
794 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000795 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800796 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000797 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000798 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800799 << "Should reject motion events with pointer ids less than 0.";
800
801 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800802 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
803 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700804 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700805 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
806 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000807 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800808 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000809 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000810 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800811 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
812
813 // Rejects motion events with duplicate pointer ids.
814 pointerProperties[0].id = 1;
815 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with duplicate pointer ids.";
826}
827
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800828/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
829
830TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
831 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000832 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800833 ASSERT_TRUE(mDispatcher->waitForIdle());
834
835 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
836}
837
838TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000839 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
840 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000841 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842
843 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
844 args.policyFlags |= POLICY_FLAG_TRUSTED;
845 mFakePolicy->assertNotifySwitchWasCalled(args);
846}
847
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700848namespace {
849
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700850static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700851// Default input dispatching timeout if there is no focused application or paused window
852// from which to determine an appropriate dispatching timeout.
853static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
854 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
855 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800856
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800857class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800858public:
Garfield Tan15601662020-09-22 15:32:38 -0700859 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700860 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800861
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000862 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700863 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700864 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 if (!consumeSeq) {
866 return nullptr;
867 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000868 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700869 return event;
870 }
871
872 /**
873 * Receive an event without acknowledging it.
874 * Return the sequence number that could later be used to send finished signal.
875 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700876 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
877 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800878 uint32_t consumeSeq;
879 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800880
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 std::chrono::time_point start = std::chrono::steady_clock::now();
882 status_t status = WOULD_BLOCK;
883 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700884 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
885 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700887 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 break;
889 }
890 }
891
892 if (status == WOULD_BLOCK) {
893 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700894 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800895 }
896
897 if (status != OK) {
898 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700899 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800900 }
901 if (event == nullptr) {
902 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800904 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 if (outEvent != nullptr) {
906 *outEvent = event;
907 }
908 return consumeSeq;
909 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800910
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700911 /**
912 * To be used together with "receiveEvent" to complete the consumption of an event.
913 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000914 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700915 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917 }
918
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000919 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700920 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 ASSERT_EQ(OK, status);
922 }
923
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700924 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000925 std::optional<int32_t> expectedDisplayId,
926 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700927 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928
929 ASSERT_NE(nullptr, event) << mName.c_str()
930 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800931 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700932 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
933 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800934
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000935 if (expectedDisplayId.has_value()) {
936 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
937 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800938
Tiger Huang8664f8c2018-10-11 19:14:35 +0800939 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700940 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800941 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700942 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000943 if (expectedFlags.has_value()) {
944 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
945 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800946 break;
947 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700948 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800949 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700950 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000951 if (expectedFlags.has_value()) {
952 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
953 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800954 break;
955 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100957 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
958 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700959 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800960 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
961 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700962 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000963 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
964 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800966 FAIL() << "Use 'consumeDragEvent' for DRAG events";
967 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800968 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800969 }
970
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800971 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700972 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973
974 if (event == nullptr) {
975 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
976 return nullptr;
977 }
978
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700979 if (event->getType() != InputEventType::MOTION) {
980 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800981 return nullptr;
982 }
983 return static_cast<MotionEvent*>(event);
984 }
985
986 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
987 MotionEvent* motionEvent = consumeMotion();
988 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
989 ASSERT_THAT(*motionEvent, matcher);
990 }
991
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100992 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700993 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 ASSERT_NE(nullptr, event) << mName.c_str()
995 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 ASSERT_EQ(InputEventType::FOCUS, event->getType())
997 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100998
999 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1000 << mName.c_str() << ": event displayId should always be NONE.";
1001
1002 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1003 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001004 }
1005
Prabir Pradhan99987712020-11-10 18:43:05 -08001006 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001007 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 ASSERT_NE(nullptr, event) << mName.c_str()
1009 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1011 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001012
1013 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1014 << mName.c_str() << ": event displayId should always be NONE.";
1015
1016 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1017 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1018 }
1019
arthurhungb89ccb02020-12-30 16:19:01 +08001020 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001021 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001022 ASSERT_NE(nullptr, event) << mName.c_str()
1023 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001024 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001025
1026 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1027 << mName.c_str() << ": event displayId should always be NONE.";
1028
1029 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1030 EXPECT_EQ(isExiting, dragEvent.isExiting());
1031 EXPECT_EQ(x, dragEvent.getX());
1032 EXPECT_EQ(y, dragEvent.getY());
1033 }
1034
Antonio Kantekf16f2832021-09-28 04:39:20 +00001035 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001036 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 ASSERT_NE(nullptr, event) << mName.c_str()
1038 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001039 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1040 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001041
1042 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1043 << mName.c_str() << ": event displayId should always be NONE.";
1044 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1045 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1046 }
1047
chaviwd1c23182019-12-20 18:44:56 -08001048 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001049 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001050 if (event == nullptr) {
1051 return;
1052 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001053 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001054 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1055 ADD_FAILURE() << "Received key event "
1056 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001058 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1059 ADD_FAILURE() << "Received motion event "
1060 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1063 ADD_FAILURE() << "Received focus event, hasFocus = "
1064 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001066 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1067 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1068 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1071 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1072 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 }
1074 FAIL() << mName.c_str()
1075 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001076 }
1077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001081
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001082private:
1083 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001084 PreallocatedInputEventFactory mEventFactory;
1085
1086 std::string mName;
1087};
1088
chaviw3277faf2021-05-19 16:45:23 -05001089class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001090public:
1091 static const int32_t WIDTH = 600;
1092 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001093
Chris Yea209fde2020-07-22 13:54:51 -07001094 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001095 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001098 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001099 base::Result<std::unique_ptr<InputChannel>> channel =
1100 dispatcher->createInputChannel(name);
1101 token = (*channel)->getConnectionToken();
1102 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001103 }
1104
1105 inputApplicationHandle->updateInfo();
1106 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1107
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001108 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001109 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001110 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001111 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001112 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001113 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001114 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001115 mInfo.globalScaleFactor = 1.0;
1116 mInfo.touchableRegion.clear();
1117 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001118 mInfo.ownerPid = WINDOW_PID;
1119 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001120 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001121 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001124 sp<FakeWindowHandle> clone(int32_t displayId) {
1125 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1126 handle->mInfo = mInfo;
1127 handle->mInfo.displayId = displayId;
1128 handle->mInfo.id = sId++;
1129 handle->mInputReceiver = mInputReceiver;
1130 return handle;
1131 }
1132
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001133 void setTouchable(bool touchable) {
1134 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1135 }
chaviwd1c23182019-12-20 18:44:56 -08001136
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001137 void setFocusable(bool focusable) {
1138 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1139 }
1140
1141 void setVisible(bool visible) {
1142 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1143 }
Vishnu Nair958da932020-08-21 17:12:37 -07001144
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001146 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001147 }
1148
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001149 void setPaused(bool paused) {
1150 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1151 }
1152
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001153 void setPreventSplitting(bool preventSplitting) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 }
1156
1157 void setSlippery(bool slippery) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1159 }
1160
1161 void setWatchOutsideTouch(bool watchOutside) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1163 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001164
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001165 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1166
1167 void setInterceptsStylus(bool interceptsStylus) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1169 }
1170
1171 void setDropInput(bool dropInput) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1173 }
1174
1175 void setDropInputIfObscured(bool dropInputIfObscured) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1177 }
1178
1179 void setNoInputChannel(bool noInputChannel) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1181 }
1182
Josep del Riob3981622023-04-18 15:49:45 +00001183 void setDisableUserActivity(bool disableUserActivity) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1185 }
1186
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001187 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1188
chaviw3277faf2021-05-19 16:45:23 -05001189 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001190
Bernardo Rufino7393d172021-02-26 13:56:11 +00001191 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1192
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001193 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001194 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001195 mInfo.touchableRegion.clear();
1196 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001197
1198 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1199 ui::Transform translate;
1200 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1201 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001202 }
1203
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001204 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1205
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001206 void setIsWallpaper(bool isWallpaper) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1208 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001209
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001210 void setDupTouchToWallpaper(bool hasWallpaper) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1212 }
chaviwd1c23182019-12-20 18:44:56 -08001213
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001214 void setTrustedOverlay(bool trustedOverlay) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1216 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001217
chaviw9eaa22c2020-07-01 16:21:27 -07001218 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1219 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1220 }
1221
1222 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001223
yunho.shinf4a80b82020-11-16 21:13:57 +09001224 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1225
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001226 KeyEvent* consumeKey(bool handled = true) {
1227 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001228 if (event == nullptr) {
1229 ADD_FAILURE() << "Consume failed : no event";
1230 return nullptr;
1231 }
1232 if (event->getType() != InputEventType::KEY) {
1233 ADD_FAILURE() << "Instead of key event, got " << *event;
1234 return nullptr;
1235 }
1236 return static_cast<KeyEvent*>(event);
1237 }
1238
1239 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1240 KeyEvent* keyEvent = consumeKey();
1241 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1242 ASSERT_THAT(*keyEvent, matcher);
1243 }
1244
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001246 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001247 }
1248
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001250 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001251 }
1252
Svet Ganov5d3bc372020-01-26 23:11:07 -08001253 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001254 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001255 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1256 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001257 }
1258
1259 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001260 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001261 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1262 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001263 }
1264
1265 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001266 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001267 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1268 }
1269
1270 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1271 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001272 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001273 expectedFlags);
1274 }
1275
Svet Ganov5d3bc372020-01-26 23:11:07 -08001276 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001277 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1278 int32_t expectedFlags = 0) {
1279 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1280 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001281 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 }
1283
1284 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 int32_t expectedFlags = 0) {
1286 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1287 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001288 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001294 expectedFlags);
1295 }
1296
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001297 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1298 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001299 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001300 expectedFlags);
1301 }
1302
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001303 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1304 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001305 MotionEvent* motionEvent = consumeMotion();
1306 ASSERT_NE(nullptr, motionEvent);
1307 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1308 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1309 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001310 }
1311
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001312 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1313 ASSERT_NE(mInputReceiver, nullptr)
1314 << "Cannot consume events from a window with no receiver";
1315 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1316 }
1317
Prabir Pradhan99987712020-11-10 18:43:05 -08001318 void consumeCaptureEvent(bool hasCapture) {
1319 ASSERT_NE(mInputReceiver, nullptr)
1320 << "Cannot consume events from a window with no receiver";
1321 mInputReceiver->consumeCaptureEvent(hasCapture);
1322 }
1323
Prabir Pradhan5893d362023-11-17 04:30:40 +00001324 const MotionEvent& consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 MotionEvent* motionEvent = consumeMotion();
Prabir Pradhan5893d362023-11-17 04:30:40 +00001326 if (nullptr == motionEvent) {
1327 LOG(FATAL) << "Did not get a motion event, but expected " << matcher;
1328 }
1329 EXPECT_THAT(*motionEvent, matcher);
1330 return *motionEvent;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001331 }
1332
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001333 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001334 std::optional<int32_t> expectedDisplayId,
1335 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001336 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1337 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1338 expectedFlags);
1339 }
1340
arthurhungb89ccb02020-12-30 16:19:01 +08001341 void consumeDragEvent(bool isExiting, float x, float y) {
1342 mInputReceiver->consumeDragEvent(isExiting, x, y);
1343 }
1344
Antonio Kantekf16f2832021-09-28 04:39:20 +00001345 void consumeTouchModeEvent(bool inTouchMode) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1349 }
1350
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001351 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001352 if (mInputReceiver == nullptr) {
1353 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1354 return std::nullopt;
1355 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001356 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001357 }
1358
1359 void finishEvent(uint32_t sequenceNum) {
1360 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1361 mInputReceiver->finishEvent(sequenceNum);
1362 }
1363
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001364 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1365 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1366 mInputReceiver->sendTimeline(inputEventId, timeline);
1367 }
1368
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001369 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001370 if (mInputReceiver == nullptr) {
1371 return nullptr;
1372 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001373 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001374 }
1375
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001376 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001377 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001378 if (event == nullptr) {
1379 ADD_FAILURE() << "Consume failed : no event";
1380 return nullptr;
1381 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001382 if (event->getType() != InputEventType::MOTION) {
1383 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001384 return nullptr;
1385 }
1386 return static_cast<MotionEvent*>(event);
1387 }
1388
Arthur Hungb92218b2018-08-14 12:00:21 +08001389 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001390 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001391 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001392 return; // Can't receive events if the window does not have input channel
1393 }
1394 ASSERT_NE(nullptr, mInputReceiver)
1395 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001396 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001397 }
1398
chaviwaf87b3e2019-10-01 16:59:28 -07001399 sp<IBinder> getToken() { return mInfo.token; }
1400
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001401 const std::string& getName() { return mName; }
1402
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001403 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001404 mInfo.ownerPid = ownerPid;
1405 mInfo.ownerUid = ownerUid;
1406 }
1407
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001408 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001409
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001410 void destroyReceiver() { mInputReceiver = nullptr; }
1411
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001412 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1413
chaviwd1c23182019-12-20 18:44:56 -08001414private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001415 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001416 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001417 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001418 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001419 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001420};
1421
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001422std::atomic<int32_t> FakeWindowHandle::sId{1};
1423
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001424class FakeMonitorReceiver {
1425public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1427 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001430
1431 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1433 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001434 }
1435
1436 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001437 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001438 }
1439
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001440 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001441
1442 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001443 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1444 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001445 }
1446
1447 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001448 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1449 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001450 }
1451
1452 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001453 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1454 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001455 }
1456
1457 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001458 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001459 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1460 WithDisplayId(expectedDisplayId),
1461 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1462 }
1463
1464 void consumeMotionPointerDown(int32_t pointerIdx) {
1465 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1466 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001467 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1468 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001469 }
1470
1471 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001472 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001473 }
1474
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001475 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001477 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001478
1479private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001480 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001481};
1482
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001483static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001484 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001485 int32_t displayId = ADISPLAY_ID_NONE,
1486 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001487 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001488 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001489 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001490 KeyEvent event;
1491 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1492
1493 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001494 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001495 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1496 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001497
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498 if (!allowKeyRepeat) {
1499 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1500 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001501 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001502 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001503}
1504
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001505static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1506 InputEventInjectionResult result =
1507 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1508 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1509 if (result != InputEventInjectionResult::TIMED_OUT) {
1510 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1511 }
1512}
1513
1514static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001515 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001516 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001517}
1518
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001519// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1520// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1521// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001522static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1523 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001524 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001525 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001526 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001527}
1528
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001529static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001530 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001531 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001532}
1533
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001534static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001535 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001536 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001537 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001538 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1540 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001541}
1542
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001543static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001544 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1545 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001546 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001547 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1548 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001549 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001550 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001551 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001552 MotionEventBuilder motionBuilder =
1553 MotionEventBuilder(action, source)
1554 .displayId(displayId)
1555 .eventTime(eventTime)
1556 .rawXCursorPosition(cursorPosition.x)
1557 .rawYCursorPosition(cursorPosition.y)
1558 .pointer(
1559 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1560 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1561 motionBuilder.downTime(eventTime);
1562 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001563
1564 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001565 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1566 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001567}
1568
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001569static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1570 int32_t displayId,
1571 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001572 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001573}
1574
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001575static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1576 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001577 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001578 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001579}
1580
Jackal Guof9696682018-10-05 12:23:23 +08001581static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001584 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001585 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1586 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001587
1588 return args;
1589}
1590
Josep del Riob3981622023-04-18 15:49:45 +00001591static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1592 int32_t displayId = ADISPLAY_ID_NONE) {
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid key event.
1595 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001596 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001597 currentTime);
1598
1599 return args;
1600}
1601
1602static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1603 int32_t displayId = ADISPLAY_ID_NONE) {
1604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1605 // Define a valid key event.
1606 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001607 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001608 AMETA_NONE, currentTime);
1609
1610 return args;
1611}
1612
Prabir Pradhan678438e2023-04-13 19:32:51 +00001613[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1614 int32_t displayId,
1615 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001616 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001617 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1618 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1619 }
1620
chaviwd1c23182019-12-20 18:44:56 -08001621 PointerProperties pointerProperties[pointerCount];
1622 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001623
chaviwd1c23182019-12-20 18:44:56 -08001624 for (size_t i = 0; i < pointerCount; i++) {
1625 pointerProperties[i].clear();
1626 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001627 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001628
chaviwd1c23182019-12-20 18:44:56 -08001629 pointerCoords[i].clear();
1630 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1631 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1632 }
Jackal Guof9696682018-10-05 12:23:23 +08001633
1634 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1635 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001636 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001637 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1638 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001639 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001640 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001641 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001642 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001643
1644 return args;
1645}
1646
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001647static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1648 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1649}
1650
chaviwd1c23182019-12-20 18:44:56 -08001651static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1652 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1653}
1654
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001655static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1656 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001657 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001658}
1659
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001660} // namespace
1661
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001662/**
1663 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1664 * broken channel.
1665 */
1666TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1668 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001669 sp<FakeWindowHandle>::make(application, mDispatcher,
1670 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001671
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001673
1674 // Window closes its channel, but the window remains.
1675 window->destroyReceiver();
1676 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1677}
1678
Arthur Hungb92218b2018-08-14 12:00:21 +08001679TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1682 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001688
1689 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001690 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001691}
1692
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001693TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001695 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1696 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001697
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001699 // Inject a MotionEvent to an unknown display.
1700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001701 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1703
1704 // Window should receive motion event.
1705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1706}
1707
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 * Calling onWindowInfosChanged once should not cause any issues.
1710 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001711 * called twice.
1712 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001713TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001715 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1716 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001718
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001719 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001724
1725 // Window should receive motion event.
1726 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1727}
1728
1729/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001730 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001731 */
1732TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001734 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1735 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001736 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1739 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001741 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001744
1745 // Window should receive motion event.
1746 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1747}
1748
Arthur Hungb92218b2018-08-14 12:00:21 +08001749// The foreground window should receive the first touch down event.
1750TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001752 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001753 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001754 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001755 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001757 mDispatcher->onWindowInfosChanged(
1758 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001762
1763 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001764 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001765 windowSecond->assertNoEvents();
1766}
1767
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001768/**
1769 * Two windows: A top window, and a wallpaper behind the window.
1770 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1771 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001772 * 1. foregroundWindow <-- dup touch to wallpaper
1773 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001774 */
1775TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1777 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001778 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001779 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001780 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001781 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001782 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001783
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001784 mDispatcher->onWindowInfosChanged(
1785 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001787 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001788 {100, 200}))
1789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1790
1791 // Both foreground window and its wallpaper should receive the touch down
1792 foregroundWindow->consumeMotionDown();
1793 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1794
1795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001796 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001797 ADISPLAY_ID_DEFAULT, {110, 200}))
1798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1799
1800 foregroundWindow->consumeMotionMove();
1801 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1802
1803 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001804 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001805 foregroundWindow->consumeMotionCancel();
1806 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1807 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1808}
1809
1810/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001811 * Two fingers down on the window, and lift off the first finger.
1812 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1813 * contains a single pointer.
1814 */
1815TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1817 sp<FakeWindowHandle> window =
1818 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1819
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001821 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1823 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1824 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001825 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001826 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1827 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1828 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1829 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001830 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001831 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1832 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1833 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1834 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001835 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1836 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1837 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1838
1839 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001841 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1842 window->consumeMotionEvent(
1843 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1844}
1845
1846/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001847 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1848 * with the following differences:
1849 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1850 * clean up the connection.
1851 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1852 * Ensure that there's no crash in the dispatcher.
1853 */
1854TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1856 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001857 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001858 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001860 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001861 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001863 mDispatcher->onWindowInfosChanged(
1864 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001866 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001867 {100, 200}))
1868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1869
1870 // Both foreground window and its wallpaper should receive the touch down
1871 foregroundWindow->consumeMotionDown();
1872 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1873
1874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001875 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001876 ADISPLAY_ID_DEFAULT, {110, 200}))
1877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1878
1879 foregroundWindow->consumeMotionMove();
1880 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1881
1882 // Wallpaper closes its channel, but the window remains.
1883 wallpaperWindow->destroyReceiver();
1884 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1885
1886 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1887 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001888 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001889 foregroundWindow->consumeMotionCancel();
1890}
1891
Arthur Hungc539dbb2022-12-08 07:45:36 +00001892class ShouldSplitTouchFixture : public InputDispatcherTest,
1893 public ::testing::WithParamInterface<bool> {};
1894INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1895 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001896/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 * A single window that receives touch (on top), and a wallpaper window underneath it.
1898 * The top window gets a multitouch gesture.
1899 * Ensure that wallpaper gets the same gesture.
1900 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001901TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001903 sp<FakeWindowHandle> foregroundWindow =
1904 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1905 foregroundWindow->setDupTouchToWallpaper(true);
1906 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907
1908 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001909 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001910 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001912 mDispatcher->onWindowInfosChanged(
1913 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914
1915 // Touch down on top window
1916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001917 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 {100, 100}))
1919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1920
1921 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001922 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001923 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1924
1925 // Second finger down on the top window
1926 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001927 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001929 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1930 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931 .build();
1932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001933 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934 InputEventInjectionSync::WAIT_FOR_RESULT))
1935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1936
Harry Cutts33476232023-01-30 19:57:29 +00001937 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1938 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001939 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001940
1941 const MotionEvent secondFingerUpEvent =
1942 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1943 .displayId(ADISPLAY_ID_DEFAULT)
1944 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001945 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1946 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001947 .build();
1948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001949 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001950 InputEventInjectionSync::WAIT_FOR_RESULT))
1951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1952 foregroundWindow->consumeMotionPointerUp(0);
1953 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1954
1955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001956 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001957 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1958 AINPUT_SOURCE_TOUCHSCREEN)
1959 .displayId(ADISPLAY_ID_DEFAULT)
1960 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001961 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001962 .x(100)
1963 .y(100))
1964 .build(),
1965 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1967 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1968 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969}
1970
1971/**
1972 * Two windows: a window on the left and window on the right.
1973 * A third window, wallpaper, is behind both windows, and spans both top windows.
1974 * The first touch down goes to the left window. A second pointer touches down on the right window.
1975 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1976 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1977 * ACTION_POINTER_DOWN(1).
1978 */
1979TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1981 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001982 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001983 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001984 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985
1986 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001987 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001989 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990
1991 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001992 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001994 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001996 mDispatcher->onWindowInfosChanged(
1997 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1998 {},
1999 0,
2000 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002001
2002 // Touch down on left window
2003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002004 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 {100, 100}))
2006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2007
2008 // Both foreground window and its wallpaper should receive the touch down
2009 leftWindow->consumeMotionDown();
2010 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2011
2012 // Second finger down on the right window
2013 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002014 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002016 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2017 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002018 .build();
2019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002020 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 InputEventInjectionSync::WAIT_FOR_RESULT))
2022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2023
2024 leftWindow->consumeMotionMove();
2025 // Since the touch is split, right window gets ACTION_DOWN
2026 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002027 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002028 expectedWallpaperFlags);
2029
2030 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002031 mDispatcher->onWindowInfosChanged(
2032 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 leftWindow->consumeMotionCancel();
2034 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2035 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2036
2037 // The pointer that's still down on the right window moves, and goes to the right window only.
2038 // As far as the dispatcher's concerned though, both pointers are still present.
2039 const MotionEvent secondFingerMoveEvent =
2040 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2041 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002042 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2043 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044 .build();
2045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002046 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002047 InputEventInjectionSync::WAIT_FOR_RESULT));
2048 rightWindow->consumeMotionMove();
2049
2050 leftWindow->assertNoEvents();
2051 rightWindow->assertNoEvents();
2052 wallpaperWindow->assertNoEvents();
2053}
2054
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055/**
2056 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2057 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2058 * The right window should receive ACTION_DOWN.
2059 */
2060TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002062 sp<FakeWindowHandle> leftWindow =
2063 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2064 leftWindow->setFrame(Rect(0, 0, 200, 200));
2065 leftWindow->setDupTouchToWallpaper(true);
2066 leftWindow->setSlippery(true);
2067
2068 sp<FakeWindowHandle> rightWindow =
2069 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2070 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002071
2072 sp<FakeWindowHandle> wallpaperWindow =
2073 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2074 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002075
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002076 mDispatcher->onWindowInfosChanged(
2077 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2078 {},
2079 0,
2080 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002081
Arthur Hungc539dbb2022-12-08 07:45:36 +00002082 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002084 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002085 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002087
2088 // Both foreground window and its wallpaper should receive the touch down
2089 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002090 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2091
Arthur Hungc539dbb2022-12-08 07:45:36 +00002092 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002094 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002095 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2097
Arthur Hungc539dbb2022-12-08 07:45:36 +00002098 leftWindow->consumeMotionCancel();
2099 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2100 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002101}
2102
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002103/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002104 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2105 * interactive, it might stop sending this flag.
2106 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2107 * to have a consistent input stream.
2108 *
2109 * Test procedure:
2110 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2111 * DOWN (new gesture).
2112 *
2113 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2114 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2115 *
2116 * We technically just need a single window here, but we are using two windows (spy on top and a
2117 * regular window below) to emulate the actual situation where it happens on the device.
2118 */
2119TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2120 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2121 sp<FakeWindowHandle> spyWindow =
2122 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2123 spyWindow->setFrame(Rect(0, 0, 200, 200));
2124 spyWindow->setTrustedOverlay(true);
2125 spyWindow->setSpy(true);
2126
2127 sp<FakeWindowHandle> window =
2128 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2129 window->setFrame(Rect(0, 0, 200, 200));
2130
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002131 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002132 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002133
2134 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002135 mDispatcher->notifyMotion(
2136 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2137 .deviceId(touchDeviceId)
2138 .policyFlags(DEFAULT_POLICY_FLAGS)
2139 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2140 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002141
Prabir Pradhan678438e2023-04-13 19:32:51 +00002142 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2143 .deviceId(touchDeviceId)
2144 .policyFlags(DEFAULT_POLICY_FLAGS)
2145 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2146 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2147 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002148 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2149 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2150 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2151 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2152
2153 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002154 mDispatcher->notifyMotion(
2155 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2156 .deviceId(touchDeviceId)
2157 .policyFlags(0)
2158 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2159 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2160 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2162 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2163
2164 // We don't need to reset the device to reproduce the issue, but the reset event typically
2165 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002166 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002167
2168 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002169 mDispatcher->notifyMotion(
2170 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2171 .deviceId(touchDeviceId)
2172 .policyFlags(DEFAULT_POLICY_FLAGS)
2173 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2174 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002175 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2176 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2177
2178 // No more events
2179 spyWindow->assertNoEvents();
2180 window->assertNoEvents();
2181}
2182
2183/**
Linnan Li907ae732023-09-05 17:14:21 +08002184 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2185 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2186 * interactive, it might stop sending this flag.
2187 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2188 * the consistency of the hover event in this case.
2189 *
2190 * Test procedure:
2191 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2192 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2193 *
2194 * We expect to receive two full streams of hover events.
2195 */
2196TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2198
2199 sp<FakeWindowHandle> window =
2200 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2201 window->setFrame(Rect(0, 0, 300, 300));
2202
2203 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2204
2205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2208 .build());
2209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2210
2211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2212 .policyFlags(DEFAULT_POLICY_FLAGS)
2213 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2214 .build());
2215 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2216
2217 // Send hover exit without the default policy flags.
2218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2219 .policyFlags(0)
2220 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2221 .build());
2222
2223 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2224
2225 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2226 // right event.
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2232
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2234 .policyFlags(DEFAULT_POLICY_FLAGS)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2236 .build());
2237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2238
2239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2240 .policyFlags(DEFAULT_POLICY_FLAGS)
2241 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2242 .build());
2243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2244}
2245
2246/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002247 * Two windows: a window on the left and a window on the right.
2248 * Mouse is hovered from the right window into the left window.
2249 * Next, we tap on the left window, where the cursor was last seen.
2250 * The second tap is done onto the right window.
2251 * The mouse and tap are from two different devices.
2252 * We technically don't need to set the downtime / eventtime for these events, but setting these
2253 * explicitly helps during debugging.
2254 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2255 * In the buggy implementation, a tap on the right window would cause a crash.
2256 */
2257TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2259 sp<FakeWindowHandle> leftWindow =
2260 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2261 leftWindow->setFrame(Rect(0, 0, 200, 200));
2262
2263 sp<FakeWindowHandle> rightWindow =
2264 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2265 rightWindow->setFrame(Rect(200, 0, 400, 200));
2266
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002267 mDispatcher->onWindowInfosChanged(
2268 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002269 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2270 // stale.
2271 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2272 const int32_t mouseDeviceId = 6;
2273 const int32_t touchDeviceId = 4;
2274 // Move the cursor from right
2275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2278 AINPUT_SOURCE_MOUSE)
2279 .deviceId(mouseDeviceId)
2280 .downTime(baseTime + 10)
2281 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 .build()));
2284 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2285
2286 // .. to the left window
2287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2290 AINPUT_SOURCE_MOUSE)
2291 .deviceId(mouseDeviceId)
2292 .downTime(baseTime + 10)
2293 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 .build()));
2296 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2297 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2298 // Now tap 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_DOWN,
2302 AINPUT_SOURCE_TOUCHSCREEN)
2303 .deviceId(touchDeviceId)
2304 .downTime(baseTime + 40)
2305 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002306 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002307 .build()));
2308 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2309 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2310
2311 // release tap
2312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2315 AINPUT_SOURCE_TOUCHSCREEN)
2316 .deviceId(touchDeviceId)
2317 .downTime(baseTime + 40)
2318 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 .build()));
2321 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2322
2323 // Tap the window on the right
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_DOWN,
2327 AINPUT_SOURCE_TOUCHSCREEN)
2328 .deviceId(touchDeviceId)
2329 .downTime(baseTime + 60)
2330 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 .build()));
2333 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2334
2335 // release tap
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_UP,
2339 AINPUT_SOURCE_TOUCHSCREEN)
2340 .deviceId(touchDeviceId)
2341 .downTime(baseTime + 60)
2342 .eventTime(baseTime + 70)
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_UP));
2346
2347 // No more events
2348 leftWindow->assertNoEvents();
2349 rightWindow->assertNoEvents();
2350}
2351
2352/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002353 * Start hovering in a window. While this hover is still active, make another window appear on top.
2354 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2355 * While the top window is present, the hovering is stopped.
2356 * Later, hovering gets resumed again.
2357 * Ensure that new hover gesture is handled correctly.
2358 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2359 * to the window that's currently being hovered over.
2360 */
2361TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2362 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2363 sp<FakeWindowHandle> window =
2364 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2365 window->setFrame(Rect(0, 0, 200, 200));
2366
2367 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002369
2370 // Start hovering in the window
2371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2373 .build());
2374 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2375
2376 // Now, an obscuring window appears!
2377 sp<FakeWindowHandle> obscuringWindow =
2378 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2379 ADISPLAY_ID_DEFAULT,
2380 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2381 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2382 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2383 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2384 obscuringWindow->setNoInputChannel(true);
2385 obscuringWindow->setFocusable(false);
2386 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002387 mDispatcher->onWindowInfosChanged(
2388 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002389
2390 // While this new obscuring window is present, the hovering is stopped
2391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2392 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2393 .build());
2394 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2395
2396 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002397 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002398
2399 // And a new hover gesture starts.
2400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2402 .build());
2403 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2404}
2405
2406/**
2407 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2408 * the obscuring window.
2409 */
2410TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2412 sp<FakeWindowHandle> window =
2413 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2414 window->setFrame(Rect(0, 0, 200, 200));
2415
2416 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002417 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002418
2419 // Start hovering in the window
2420 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2421 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2422 .build());
2423 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2424
2425 // Now, an obscuring window appears!
2426 sp<FakeWindowHandle> obscuringWindow =
2427 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2428 ADISPLAY_ID_DEFAULT,
2429 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2430 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2431 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2432 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2433 obscuringWindow->setNoInputChannel(true);
2434 obscuringWindow->setFocusable(false);
2435 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002436 mDispatcher->onWindowInfosChanged(
2437 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002438
2439 // While this new obscuring window is present, the hovering continues. The event can't go to the
2440 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2442 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2443 .build());
2444 obscuringWindow->assertNoEvents();
2445 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2446
2447 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002448 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002449
2450 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2451 // so it should generate a HOVER_ENTER
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2453 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2456
2457 // Now the MOVE should be getting dispatched normally
2458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2459 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2460 .build());
2461 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2462}
2463
2464/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002465 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2466 * events are delivered to the window.
2467 */
2468TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2470 sp<FakeWindowHandle> window =
2471 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2472 window->setFrame(Rect(0, 0, 200, 200));
2473 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2474
2475 // Start hovering in the window
2476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2477 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2478 .build());
2479 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2480
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2485
2486 // Scroll with the mouse
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2488 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2489 .build());
2490 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2491}
2492
2493using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2494
2495/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002496 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2497 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002498 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002499TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2501 sp<FakeWindowHandle> window =
2502 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2503 window->setFrame(Rect(0, 0, 200, 200));
2504
2505 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2506
2507 constexpr int32_t touchDeviceId = 4;
2508 constexpr int32_t stylusDeviceId = 2;
2509
2510 // Stylus down
2511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2512 .deviceId(stylusDeviceId)
2513 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2514 .build());
2515 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2516
2517 // Touch down
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2521 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002522
2523 // Touch move
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2525 .deviceId(touchDeviceId)
2526 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2527 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002528 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002529
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002530 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2532 .deviceId(stylusDeviceId)
2533 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2534 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002535 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2536 WithCoords(101, 111)));
2537
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002538 window->assertNoEvents();
2539}
2540
2541/**
2542 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002543 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002544 * Similar test as above, but with added SPY window.
2545 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002546TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2548 sp<FakeWindowHandle> window =
2549 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2550 sp<FakeWindowHandle> spyWindow =
2551 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2552 spyWindow->setFrame(Rect(0, 0, 200, 200));
2553 spyWindow->setTrustedOverlay(true);
2554 spyWindow->setSpy(true);
2555 window->setFrame(Rect(0, 0, 200, 200));
2556
2557 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2558
2559 constexpr int32_t touchDeviceId = 4;
2560 constexpr int32_t stylusDeviceId = 2;
2561
2562 // Stylus down
2563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2564 .deviceId(stylusDeviceId)
2565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2566 .build());
2567 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2568 spyWindow->consumeMotionEvent(
2569 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2570
2571 // Touch down
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2573 .deviceId(touchDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2575 .build());
2576
2577 // Touch move
2578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2579 .deviceId(touchDeviceId)
2580 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2581 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002582
2583 // Touch is ignored because stylus is already down
2584
2585 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002586 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2587 .deviceId(stylusDeviceId)
2588 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2589 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002590 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2591 WithCoords(101, 111)));
2592 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2593 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002594
2595 window->assertNoEvents();
2596 spyWindow->assertNoEvents();
2597}
2598
2599/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002600 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002601 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002602 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002603TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2605 sp<FakeWindowHandle> window =
2606 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2607 window->setFrame(Rect(0, 0, 200, 200));
2608
2609 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2610
2611 constexpr int32_t touchDeviceId = 4;
2612 constexpr int32_t stylusDeviceId = 2;
2613
2614 // Stylus down on the window
2615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2616 .deviceId(stylusDeviceId)
2617 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2618 .build());
2619 window->consumeMotionEvent(
2620 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2621
2622 // Touch down on window
2623 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2624 .deviceId(touchDeviceId)
2625 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2626 .build());
2627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2628 .deviceId(touchDeviceId)
2629 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2630 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002631
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002632 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002633
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002634 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2636 .deviceId(stylusDeviceId)
2637 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2638 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002639 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2640 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002641
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002642 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2644 .deviceId(touchDeviceId)
2645 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2646 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002647 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648}
2649
2650/**
2651 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002652 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002653 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002654TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2656 sp<FakeWindowHandle> window =
2657 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2658 window->setFrame(Rect(0, 0, 200, 200));
2659
2660 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2661
2662 constexpr int32_t touchDeviceId = 4;
2663 constexpr int32_t stylusDeviceId = 2;
2664
2665 // Touch down on window
2666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2667 .deviceId(touchDeviceId)
2668 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2669 .build());
2670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2671 .deviceId(touchDeviceId)
2672 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2673 .build());
2674 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2675 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2676
2677 // Stylus hover on the window
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2679 .deviceId(stylusDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2681 .build());
2682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2683 .deviceId(stylusDeviceId)
2684 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2685 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002686 // Stylus hover movement causes touch to be canceled
2687 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2688 WithCoords(141, 146)));
2689 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2690 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2691 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2692 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002693
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002694 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2696 .deviceId(touchDeviceId)
2697 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2698 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002699
2700 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002701}
2702
2703/**
2704 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2705 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2706 * become active.
2707 */
2708TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2710 sp<FakeWindowHandle> window =
2711 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2712 window->setFrame(Rect(0, 0, 200, 200));
2713
2714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2715
2716 constexpr int32_t stylusDeviceId1 = 3;
2717 constexpr int32_t stylusDeviceId2 = 5;
2718
2719 // Touch down on window
2720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2721 .deviceId(stylusDeviceId1)
2722 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2723 .build());
2724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2725 .deviceId(stylusDeviceId1)
2726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2727 .build());
2728 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2729 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2730
2731 // Second stylus down
2732 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2733 .deviceId(stylusDeviceId2)
2734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2735 .build());
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2737 .deviceId(stylusDeviceId2)
2738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2739 .build());
2740
2741 // First stylus is canceled, second one takes over.
2742 window->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2744 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2745 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2746
2747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2748 .deviceId(stylusDeviceId1)
2749 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2750 .build());
2751 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002752 window->assertNoEvents();
2753}
2754
2755/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002756 * One window. Touch down on the window. Then, stylus down on the window from another device.
2757 * Ensure that is canceled, because stylus down should be preferred over touch.
2758 */
2759TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2761 sp<FakeWindowHandle> window =
2762 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2763 window->setFrame(Rect(0, 0, 200, 200));
2764
2765 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2766
2767 constexpr int32_t touchDeviceId = 4;
2768 constexpr int32_t stylusDeviceId = 2;
2769
2770 // Touch down on window
2771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2772 .deviceId(touchDeviceId)
2773 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2774 .build());
2775 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2776 .deviceId(touchDeviceId)
2777 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2778 .build());
2779 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2780 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2781
2782 // Stylus down on the window
2783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2784 .deviceId(stylusDeviceId)
2785 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2786 .build());
2787 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2788 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2789
2790 // Subsequent stylus movements are delivered correctly
2791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2792 .deviceId(stylusDeviceId)
2793 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2794 .build());
2795 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2796 WithCoords(101, 111)));
2797}
2798
2799/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002800 * Two windows: a window on the left and a window on the right.
2801 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2802 * down. Then, on the left window, also place second touch pointer down.
2803 * This test tries to reproduce a crash.
2804 * In the buggy implementation, second pointer down on the left window would cause a crash.
2805 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002806TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2808 sp<FakeWindowHandle> leftWindow =
2809 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2810 leftWindow->setFrame(Rect(0, 0, 200, 200));
2811
2812 sp<FakeWindowHandle> rightWindow =
2813 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2814 rightWindow->setFrame(Rect(200, 0, 400, 200));
2815
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002816 mDispatcher->onWindowInfosChanged(
2817 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002818
2819 const int32_t touchDeviceId = 4;
2820 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821
2822 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2824 .deviceId(mouseDeviceId)
2825 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2826 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002827 leftWindow->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2829
2830 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2832 .deviceId(mouseDeviceId)
2833 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2834 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2835 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836
2837 leftWindow->consumeMotionEvent(
2838 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2839 leftWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2841
Prabir Pradhan678438e2023-04-13 19:32:51 +00002842 mDispatcher->notifyMotion(
2843 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2844 .deviceId(mouseDeviceId)
2845 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2846 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2847 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2848 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002849 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2850
2851 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2853 .deviceId(touchDeviceId)
2854 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2855 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002856 leftWindow->assertNoEvents();
2857
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2859
2860 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002861 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2862 .deviceId(touchDeviceId)
2863 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2864 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2865 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002866 // Since this is now a new splittable pointer going down on the left window, and it's coming
2867 // from a different device, the current gesture in the left window (pointer down) should first
2868 // be canceled.
2869 leftWindow->consumeMotionEvent(
2870 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002871 leftWindow->consumeMotionEvent(
2872 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2873 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2874 // current implementation.
2875 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2876 rightWindow->consumeMotionEvent(
2877 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2878
2879 leftWindow->assertNoEvents();
2880 rightWindow->assertNoEvents();
2881}
2882
2883/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002884 * Two windows: a window on the left and a window on the right.
2885 * Mouse is hovered on the left window and stylus is hovered on the right window.
2886 */
2887TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2889 sp<FakeWindowHandle> leftWindow =
2890 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2891 leftWindow->setFrame(Rect(0, 0, 200, 200));
2892
2893 sp<FakeWindowHandle> rightWindow =
2894 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2895 rightWindow->setFrame(Rect(200, 0, 400, 200));
2896
2897 mDispatcher->onWindowInfosChanged(
2898 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2899
2900 const int32_t stylusDeviceId = 3;
2901 const int32_t mouseDeviceId = 6;
2902
2903 // Start hovering over the left window
2904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2905 .deviceId(mouseDeviceId)
2906 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2907 .build());
2908 leftWindow->consumeMotionEvent(
2909 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2910
2911 // Stylus hovered on right window
2912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2913 .deviceId(stylusDeviceId)
2914 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2915 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002916 rightWindow->consumeMotionEvent(
2917 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2918
2919 // Subsequent HOVER_MOVE events are dispatched correctly.
2920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2921 .deviceId(mouseDeviceId)
2922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2923 .build());
2924 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002925 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002926
2927 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2928 .deviceId(stylusDeviceId)
2929 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2930 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002932 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933
2934 leftWindow->assertNoEvents();
2935 rightWindow->assertNoEvents();
2936}
2937
2938/**
2939 * Three windows: a window on the left and a window on the right.
2940 * And a spy window that's positioned above all of them.
2941 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2942 * Check the stream that's received by the spy.
2943 */
2944TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2946
2947 sp<FakeWindowHandle> spyWindow =
2948 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2949 spyWindow->setFrame(Rect(0, 0, 400, 400));
2950 spyWindow->setTrustedOverlay(true);
2951 spyWindow->setSpy(true);
2952
2953 sp<FakeWindowHandle> leftWindow =
2954 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2955 leftWindow->setFrame(Rect(0, 0, 200, 200));
2956
2957 sp<FakeWindowHandle> rightWindow =
2958 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2959
2960 rightWindow->setFrame(Rect(200, 0, 400, 200));
2961
2962 mDispatcher->onWindowInfosChanged(
2963 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2964
2965 const int32_t stylusDeviceId = 1;
2966 const int32_t touchDeviceId = 2;
2967
2968 // Stylus down on the left window
2969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2970 .deviceId(stylusDeviceId)
2971 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2972 .build());
2973 leftWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2975 spyWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977
2978 // Touch down on the right window
2979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2980 .deviceId(touchDeviceId)
2981 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2982 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002983 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002984 rightWindow->consumeMotionEvent(
2985 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002987 // Spy window does not receive touch events, because stylus events take precedence, and it
2988 // already has an active stylus gesture.
2989
2990 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2992 .deviceId(stylusDeviceId)
2993 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2994 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002995 leftWindow->consumeMotionEvent(
2996 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2997 spyWindow->consumeMotionEvent(
2998 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002999
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003000 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3002 .deviceId(touchDeviceId)
3003 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3004 .build());
3005 rightWindow->consumeMotionEvent(
3006 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003007
3008 spyWindow->assertNoEvents();
3009 leftWindow->assertNoEvents();
3010 rightWindow->assertNoEvents();
3011}
3012
3013/**
3014 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3015 * both.
3016 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003017 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003018 * At the same time, left and right should be getting independent streams of hovering and touch,
3019 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003020 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003021TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3023
3024 sp<FakeWindowHandle> spyWindow =
3025 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3026 spyWindow->setFrame(Rect(0, 0, 400, 400));
3027 spyWindow->setTrustedOverlay(true);
3028 spyWindow->setSpy(true);
3029
3030 sp<FakeWindowHandle> leftWindow =
3031 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3032 leftWindow->setFrame(Rect(0, 0, 200, 200));
3033
3034 sp<FakeWindowHandle> rightWindow =
3035 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3036 rightWindow->setFrame(Rect(200, 0, 400, 200));
3037
3038 mDispatcher->onWindowInfosChanged(
3039 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3040
3041 const int32_t stylusDeviceId = 1;
3042 const int32_t touchDeviceId = 2;
3043
3044 // Stylus hover on the left window
3045 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3046 .deviceId(stylusDeviceId)
3047 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3048 .build());
3049 leftWindow->consumeMotionEvent(
3050 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3051 spyWindow->consumeMotionEvent(
3052 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003054 // Touch down on the right window. Spy doesn't receive this touch because it already has
3055 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3057 .deviceId(touchDeviceId)
3058 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3059 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003060 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003061 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003062 rightWindow->consumeMotionEvent(
3063 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3064
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003065 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3067 .deviceId(stylusDeviceId)
3068 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3069 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003070 leftWindow->consumeMotionEvent(
3071 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003072 spyWindow->consumeMotionEvent(
3073 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003075 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3077 .deviceId(touchDeviceId)
3078 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3079 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003080 rightWindow->consumeMotionEvent(
3081 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3082
3083 spyWindow->assertNoEvents();
3084 leftWindow->assertNoEvents();
3085 rightWindow->assertNoEvents();
3086}
3087
3088/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003089 * On a single window, use two different devices: mouse and touch.
3090 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3091 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3092 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3093 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3094 * represent a new gesture.
3095 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003096TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3098 sp<FakeWindowHandle> window =
3099 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3100 window->setFrame(Rect(0, 0, 400, 400));
3101
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003102 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003103
3104 const int32_t touchDeviceId = 4;
3105 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003107 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3109 .deviceId(touchDeviceId)
3110 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3116 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3117 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3120 .deviceId(touchDeviceId)
3121 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3122 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3123 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3125 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3126 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3127
3128 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3130 .deviceId(mouseDeviceId)
3131 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3132 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3133 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134
3135 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003136 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3138
Prabir Pradhan678438e2023-04-13 19:32:51 +00003139 mDispatcher->notifyMotion(
3140 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3141 .deviceId(mouseDeviceId)
3142 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3143 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3144 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3145 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003146 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3147
3148 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003149 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3150 .deviceId(touchDeviceId)
3151 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3152 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3153 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003154 // Since we already canceled this touch gesture, it will be ignored until a completely new
3155 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3156 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3157 // However, mouse movements should continue to work.
3158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3159 .deviceId(mouseDeviceId)
3160 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3161 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3162 .build());
3163 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3164
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003165 window->assertNoEvents();
3166}
3167
3168/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003169 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3170 * the injected event.
3171 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003172TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3174 sp<FakeWindowHandle> window =
3175 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3176 window->setFrame(Rect(0, 0, 400, 400));
3177
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003178 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003179
3180 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003181 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3182 // completion.
3183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003184 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003185 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3186 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003187 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003188 .build()));
3189 window->consumeMotionEvent(
3190 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3191
3192 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3193 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003194 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3195 .deviceId(touchDeviceId)
3196 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3197 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003198
3199 window->consumeMotionEvent(
3200 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3201 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3202}
3203
3204/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003205 * This test is similar to the test above, but the sequence of injected events is different.
3206 *
3207 * Two windows: a window on the left and a window on the right.
3208 * Mouse is hovered over the left window.
3209 * Next, we tap on the left window, where the cursor was last seen.
3210 *
3211 * After that, we inject one finger down onto the right window, and then a second finger down onto
3212 * the left window.
3213 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3214 * window (first), and then another on the left window (second).
3215 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3216 * In the buggy implementation, second finger down on the left window would cause a crash.
3217 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003218TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3220 sp<FakeWindowHandle> leftWindow =
3221 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3222 leftWindow->setFrame(Rect(0, 0, 200, 200));
3223
3224 sp<FakeWindowHandle> rightWindow =
3225 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3226 rightWindow->setFrame(Rect(200, 0, 400, 200));
3227
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003228 mDispatcher->onWindowInfosChanged(
3229 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003230
3231 const int32_t mouseDeviceId = 6;
3232 const int32_t touchDeviceId = 4;
3233 // Hover over the left window. Keep the cursor there.
3234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003235 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003236 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3237 AINPUT_SOURCE_MOUSE)
3238 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003239 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003240 .build()));
3241 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3242
3243 // Tap on left window
3244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003246 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3247 AINPUT_SOURCE_TOUCHSCREEN)
3248 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003249 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003250 .build()));
3251
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003254 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3255 AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 .build()));
3259 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3260 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3261 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3262
3263 // First finger down on right window
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_DOWN,
3267 AINPUT_SOURCE_TOUCHSCREEN)
3268 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003270 .build()));
3271 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3272
3273 // Second finger down on the left window
3274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003275 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003276 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3277 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003278 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3279 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003280 .build()));
3281 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3282 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3283
3284 // No more events
3285 leftWindow->assertNoEvents();
3286 rightWindow->assertNoEvents();
3287}
3288
3289/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003290 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3291 * While the touch is down, new hover events from the stylus device should be ignored. After the
3292 * touch is gone, stylus hovering should start working again.
3293 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003294TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003295 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3296 sp<FakeWindowHandle> window =
3297 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3298 window->setFrame(Rect(0, 0, 200, 200));
3299
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003300 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003301
3302 const int32_t stylusDeviceId = 5;
3303 const int32_t touchDeviceId = 4;
3304 // Start hovering with stylus
3305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003306 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003307 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003308 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003310 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312
3313 // Finger down on the window
3314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003315 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003316 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003317 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003320 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003321
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003322 // Continue hovering with stylus.
3323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003324 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003325 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3326 AINPUT_SOURCE_STYLUS)
3327 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003329 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003330 // Hovers continue to work
3331 window->consumeMotionEvent(
3332 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003333
3334 // Lift up the finger
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_UP,
3338 AINPUT_SOURCE_TOUCHSCREEN)
3339 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003340 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003341 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003342
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003344 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3346 AINPUT_SOURCE_STYLUS)
3347 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003348 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003349 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003350 window->consumeMotionEvent(
3351 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003352 window->assertNoEvents();
3353}
3354
3355/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003356 * A spy window above a window with no input channel.
3357 * Start hovering with a stylus device, and then tap with it.
3358 * Ensure spy window receives the entire sequence.
3359 */
3360TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3362 sp<FakeWindowHandle> spyWindow =
3363 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3364 spyWindow->setFrame(Rect(0, 0, 200, 200));
3365 spyWindow->setTrustedOverlay(true);
3366 spyWindow->setSpy(true);
3367 sp<FakeWindowHandle> window =
3368 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3369 window->setNoInputChannel(true);
3370 window->setFrame(Rect(0, 0, 200, 200));
3371
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003372 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003373
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003374 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3376 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3377 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003378 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3379 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3381 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3382 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003383 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3384
3385 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3388 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003389 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3390
3391 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3393 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3394 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003395 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3396
3397 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3399 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3400 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003401 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3402 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3405 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003406 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3407
3408 // No more events
3409 spyWindow->assertNoEvents();
3410 window->assertNoEvents();
3411}
3412
3413/**
3414 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3415 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3416 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3417 * While the mouse is down, new move events from the touch device should be ignored.
3418 */
3419TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3421 sp<FakeWindowHandle> spyWindow =
3422 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3423 spyWindow->setFrame(Rect(0, 0, 200, 200));
3424 spyWindow->setTrustedOverlay(true);
3425 spyWindow->setSpy(true);
3426 sp<FakeWindowHandle> window =
3427 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3428 window->setFrame(Rect(0, 0, 200, 200));
3429
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003430 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003431
3432 const int32_t mouseDeviceId = 7;
3433 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003434
3435 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3437 .deviceId(mouseDeviceId)
3438 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3439 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003440 spyWindow->consumeMotionEvent(
3441 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3442 window->consumeMotionEvent(
3443 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3444
3445 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3447 .deviceId(touchDeviceId)
3448 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3449 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003450 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3451 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3452 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3453 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3454
Prabir Pradhan678438e2023-04-13 19:32:51 +00003455 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3456 .deviceId(touchDeviceId)
3457 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3458 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003459 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3460 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3461
3462 // Pilfer the stream
3463 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3464 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3465
Prabir Pradhan678438e2023-04-13 19:32:51 +00003466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3467 .deviceId(touchDeviceId)
3468 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3469 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003470 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3471
3472 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3474 .deviceId(mouseDeviceId)
3475 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3476 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3477 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003478
3479 spyWindow->consumeMotionEvent(
3480 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3481 spyWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3484
Prabir Pradhan678438e2023-04-13 19:32:51 +00003485 mDispatcher->notifyMotion(
3486 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3487 .deviceId(mouseDeviceId)
3488 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3489 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3490 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3491 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003492 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3493 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3494
3495 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3497 .deviceId(mouseDeviceId)
3498 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003501 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3502 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3503
3504 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3506 .deviceId(touchDeviceId)
3507 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3508 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003509
3510 // No more events
3511 spyWindow->assertNoEvents();
3512 window->assertNoEvents();
3513}
3514
3515/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003516 * On the display, have a single window, and also an area where there's no window.
3517 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3518 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3519 */
3520TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3522 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003523 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003524
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003525 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003526
3527 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003528 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003529
3530 mDispatcher->waitForIdle();
3531 window->assertNoEvents();
3532
3533 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003534 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003535 mDispatcher->waitForIdle();
3536 window->consumeMotionDown();
3537}
3538
3539/**
3540 * Same test as above, but instead of touching the empty space, the first touch goes to
3541 * non-touchable window.
3542 */
3543TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3544 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3545 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003546 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003547 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3548 window1->setTouchable(false);
3549 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003550 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003551 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3552
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003553 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003554
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003555 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003556 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003557
3558 mDispatcher->waitForIdle();
3559 window1->assertNoEvents();
3560 window2->assertNoEvents();
3561
3562 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003563 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003564 mDispatcher->waitForIdle();
3565 window2->consumeMotionDown();
3566}
3567
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003568/**
3569 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3570 * to the event time of the first ACTION_DOWN sent to the particular window.
3571 */
3572TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3574 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003575 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003576 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3577 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003578 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003579 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3580
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003581 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003582
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003583 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003584 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003585
3586 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003587
3588 MotionEvent* motionEvent1 = window1->consumeMotion();
3589 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003590 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3592 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003593
3594 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003595 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003596 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003597 MotionEvent* motionEvent2 = window2->consumeMotion();
3598 ASSERT_NE(motionEvent2, nullptr);
3599 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003600 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003601 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602
3603 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003604 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003605 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003606 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003607
3608 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003609 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003610 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003611 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003612
3613 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3614 window1->consumeMotionMove();
3615 window1->assertNoEvents();
3616
3617 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003618 mDispatcher->notifyMotion(
3619 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003620 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003621 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622
Prabir Pradhan678438e2023-04-13 19:32:51 +00003623 mDispatcher->notifyMotion(
3624 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003625 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003626 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003627}
3628
Garfield Tandf26e862020-07-01 20:18:19 -07003629TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003631 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003632 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003633 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003634 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003635 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003636 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003637
3638 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3639
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003640 mDispatcher->onWindowInfosChanged(
3641 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003642
3643 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003645 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003646 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3647 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003648 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003649 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003650 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003651
3652 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003655 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3656 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003657 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003658 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003659 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3660 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003661
3662 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003664 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003665 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3666 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003667 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003668 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003669 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3670 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003671
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003673 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003674 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3675 AINPUT_SOURCE_MOUSE)
3676 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3677 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003678 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003679 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003680 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003681
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003683 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003684 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3685 AINPUT_SOURCE_MOUSE)
3686 .buttonState(0)
3687 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003689 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003690 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003691
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003693 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003694 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3695 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003696 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003697 .build()));
3698 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3699
3700 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003702 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003703 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3704 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003705 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003706 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003707 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003708
3709 // No more events
3710 windowLeft->assertNoEvents();
3711 windowRight->assertNoEvents();
3712}
3713
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003714/**
3715 * Put two fingers down (and don't release them) and click the mouse button.
3716 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3717 * currently active gesture should be canceled, and the new one should proceed.
3718 */
3719TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3721 sp<FakeWindowHandle> window =
3722 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3723 window->setFrame(Rect(0, 0, 600, 800));
3724
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003726
3727 const int32_t touchDeviceId = 4;
3728 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003729
3730 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3732 .deviceId(touchDeviceId)
3733 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3734 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003735
Prabir Pradhan678438e2023-04-13 19:32:51 +00003736 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3737 .deviceId(touchDeviceId)
3738 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3739 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3740 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003741 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3742 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3743
3744 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3746 .deviceId(mouseDeviceId)
3747 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3749 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003750 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3751 WithPointerCount(2u)));
3752 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3753
Prabir Pradhan678438e2023-04-13 19:32:51 +00003754 mDispatcher->notifyMotion(
3755 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3756 .deviceId(mouseDeviceId)
3757 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3758 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3759 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003761 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3762
3763 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3764 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3766 .deviceId(touchDeviceId)
3767 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3768 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3769 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003770 window->assertNoEvents();
3771}
3772
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003773TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3775
3776 sp<FakeWindowHandle> spyWindow =
3777 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3778 spyWindow->setFrame(Rect(0, 0, 600, 800));
3779 spyWindow->setTrustedOverlay(true);
3780 spyWindow->setSpy(true);
3781 sp<FakeWindowHandle> window =
3782 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3783 window->setFrame(Rect(0, 0, 600, 800));
3784
3785 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003786 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003787
3788 // Send mouse cursor to the window
3789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003790 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003791 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3792 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003793 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003794 .build()));
3795
3796 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3797 WithSource(AINPUT_SOURCE_MOUSE)));
3798 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3799 WithSource(AINPUT_SOURCE_MOUSE)));
3800
3801 window->assertNoEvents();
3802 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003803}
3804
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003805TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3807
3808 sp<FakeWindowHandle> spyWindow =
3809 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3810 spyWindow->setFrame(Rect(0, 0, 600, 800));
3811 spyWindow->setTrustedOverlay(true);
3812 spyWindow->setSpy(true);
3813 sp<FakeWindowHandle> window =
3814 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3815 window->setFrame(Rect(0, 0, 600, 800));
3816
3817 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003818 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003819
3820 // Send mouse cursor to the window
3821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003822 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003823 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3824 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003825 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003826 .build()));
3827
3828 // Move mouse cursor
3829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003830 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003831 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3832 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003833 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003834 .build()));
3835
3836 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3837 WithSource(AINPUT_SOURCE_MOUSE)));
3838 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3839 WithSource(AINPUT_SOURCE_MOUSE)));
3840 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3841 WithSource(AINPUT_SOURCE_MOUSE)));
3842 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3843 WithSource(AINPUT_SOURCE_MOUSE)));
3844 // Touch down on the window
3845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003846 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003847 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3848 AINPUT_SOURCE_TOUCHSCREEN)
3849 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003850 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003851 .build()));
3852 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3853 WithSource(AINPUT_SOURCE_MOUSE)));
3854 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3855 WithSource(AINPUT_SOURCE_MOUSE)));
3856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3857 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3858 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3859 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3860
3861 // pilfer the motion, retaining the gesture on the spy window.
3862 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3863 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3864 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3865
3866 // Touch UP on the window
3867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003868 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003869 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3870 AINPUT_SOURCE_TOUCHSCREEN)
3871 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003872 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003873 .build()));
3874 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3875 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3876
3877 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3878 // to send a new gesture. It should again go to both windows (spy and the window below), just
3879 // like the first gesture did, before pilfering. The window configuration has not changed.
3880
3881 // One more tap - DOWN
3882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003883 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003884 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3885 AINPUT_SOURCE_TOUCHSCREEN)
3886 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003887 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003888 .build()));
3889 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3890 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3891 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3892 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3893
3894 // Touch UP on the window
3895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003896 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003897 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3898 AINPUT_SOURCE_TOUCHSCREEN)
3899 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003900 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003901 .build()));
3902 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3903 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3904 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3905 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3906
3907 window->assertNoEvents();
3908 spyWindow->assertNoEvents();
3909}
3910
Garfield Tandf26e862020-07-01 20:18:19 -07003911// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3912// directly in this test.
3913TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003915 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003916 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003917 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003918
3919 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3920
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003921 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003922
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003924 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003925 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3926 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003927 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003928 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003929 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003930 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003932 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003933 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3934 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003935 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003936 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003937 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3938 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003939
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003941 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003942 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3943 AINPUT_SOURCE_MOUSE)
3944 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3945 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003946 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003947 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003948 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003949
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003951 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003952 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3953 AINPUT_SOURCE_MOUSE)
3954 .buttonState(0)
3955 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003957 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003958 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003959
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003961 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003962 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3963 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003964 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003965 .build()));
3966 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3967
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003968 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3969 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3970 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003971 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003972 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3973 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003974 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003975 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003976 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003977}
3978
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003979/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003980 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3981 * is generated.
3982 */
3983TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3985 sp<FakeWindowHandle> window =
3986 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3987 window->setFrame(Rect(0, 0, 1200, 800));
3988
3989 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003992
3993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003994 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003995 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3996 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003997 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003998 .build()));
3999 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4000
4001 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004002 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004003 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4004}
4005
4006/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004007 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4008 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004009TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4010 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4011 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4013 sp<FakeWindowHandle> window =
4014 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4015 window->setFrame(Rect(0, 0, 1200, 800));
4016
4017 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4018
4019 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4020
4021 MotionEventBuilder hoverEnterBuilder =
4022 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4024 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4026 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4028 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4029 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4030 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4031}
4032
4033/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004034 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4035 */
4036TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4038 sp<FakeWindowHandle> window =
4039 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4040 window->setFrame(Rect(0, 0, 100, 100));
4041
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004042 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004043
4044 const int32_t mouseDeviceId = 7;
4045 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004046
4047 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4049 .deviceId(mouseDeviceId)
4050 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4051 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004052 window->consumeMotionEvent(
4053 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4054
4055 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4057 .deviceId(touchDeviceId)
4058 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4059 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004060
4061 window->consumeMotionEvent(
4062 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4063 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4064}
4065
4066/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004067 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004068 * The tap causes a HOVER_EXIT event to be generated because the current event
4069 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004070 */
4071TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4073 sp<FakeWindowHandle> window =
4074 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4075 window->setFrame(Rect(0, 0, 100, 100));
4076
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004077 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4079 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4080 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004081 ASSERT_NO_FATAL_FAILURE(
4082 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4083 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004084
4085 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004086 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4087 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4088 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004089 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004090 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4091 WithSource(AINPUT_SOURCE_MOUSE))));
4092
4093 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004094 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4095 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4096
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4098 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4099 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004100 ASSERT_NO_FATAL_FAILURE(
4101 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4102 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4103}
4104
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004105TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4107 sp<FakeWindowHandle> windowDefaultDisplay =
4108 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4109 ADISPLAY_ID_DEFAULT);
4110 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4111 sp<FakeWindowHandle> windowSecondDisplay =
4112 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4113 SECOND_DISPLAY_ID);
4114 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4115
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004116 mDispatcher->onWindowInfosChanged(
4117 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004118
4119 // Set cursor position in window in default display and check that hover enter and move
4120 // events are generated.
4121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004122 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004123 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4124 AINPUT_SOURCE_MOUSE)
4125 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004127 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004128 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004129
4130 // Remove all windows in secondary display and check that no event happens on window in
4131 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004132 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4133
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004134 windowDefaultDisplay->assertNoEvents();
4135
4136 // Move cursor position in window in default display and check that only hover move
4137 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004138 mDispatcher->onWindowInfosChanged(
4139 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004141 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004142 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4143 AINPUT_SOURCE_MOUSE)
4144 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004146 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004147 windowDefaultDisplay->consumeMotionEvent(
4148 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4149 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004150 windowDefaultDisplay->assertNoEvents();
4151}
4152
Garfield Tan00f511d2019-06-12 16:55:40 -07004153TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004155
4156 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004157 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004158 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004159 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004160 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004161 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004162
4163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004165 mDispatcher->onWindowInfosChanged(
4166 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004167
4168 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4169 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004171 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004172 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004173 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004174 windowRight->assertNoEvents();
4175}
4176
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004177TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004179 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4180 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004181 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004184 setFocusedWindow(window);
4185
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004186 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004187
Prabir Pradhan678438e2023-04-13 19:32:51 +00004188 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004189
4190 // Window should receive key down event.
4191 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4192
4193 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4194 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004195 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004196 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004197 AKEY_EVENT_FLAG_CANCELED);
4198}
4199
4200TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004201 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004202 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4203 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004204
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004205 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004206
Prabir Pradhan678438e2023-04-13 19:32:51 +00004207 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4208 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004209
4210 // Window should receive motion down event.
4211 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4212
4213 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4214 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004215 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004216 window->consumeMotionEvent(
4217 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004218}
4219
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004220TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4222 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4223 "Fake Window", ADISPLAY_ID_DEFAULT);
4224
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004225 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004226
4227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4228 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4229 .build());
4230
4231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4232
4233 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4234 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4235 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4236
4237 // After the device has been reset, a new hovering stream can be sent to the window
4238 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4239 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4240 .build());
4241 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4242}
4243
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004244TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4245 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004246 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4247 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004248 window->setFocusable(true);
4249
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004250 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004251 setFocusedWindow(window);
4252
4253 window->consumeFocusEvent(true);
4254
Prabir Pradhan678438e2023-04-13 19:32:51 +00004255 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004256 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4257 const nsecs_t injectTime = keyArgs.eventTime;
4258 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004259 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004260 // The dispatching time should be always greater than or equal to intercept key timeout.
4261 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4262 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4263 std::chrono::nanoseconds(interceptKeyTimeout).count());
4264}
4265
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004266/**
4267 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4268 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004269TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004271 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4272 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004273 window->setFocusable(true);
4274
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004276 setFocusedWindow(window);
4277
4278 window->consumeFocusEvent(true);
4279
Prabir Pradhan678438e2023-04-13 19:32:51 +00004280 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004281 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004282
4283 // Set a value that's significantly larger than the default consumption timeout. If the
4284 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4285 mFakePolicy->setInterceptKeyTimeout(600ms);
4286 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4287 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004288 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4289}
4290
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004291/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004292 * Two windows. First is a regular window. Second does not overlap with the first, and has
4293 * WATCH_OUTSIDE_TOUCH.
4294 * Both windows are owned by the same UID.
4295 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4296 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4297 */
4298TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004300 sp<FakeWindowHandle> window =
4301 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004302 window->setFrame(Rect{0, 0, 100, 100});
4303
4304 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004305 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004306 ADISPLAY_ID_DEFAULT);
4307 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4308 outsideWindow->setWatchOutsideTouch(true);
4309 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004310 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004311
4312 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004313 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4314 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4315 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004316 window->consumeMotionDown();
4317 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4318 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4319 outsideWindow->consumeMotionEvent(
4320 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4321}
4322
4323/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004324 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4325 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4326 * ACTION_OUTSIDE event is sent per gesture.
4327 */
4328TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4329 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4330 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4332 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004333 window->setWatchOutsideTouch(true);
4334 window->setFrame(Rect{0, 0, 100, 100});
4335 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004336 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4337 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004338 secondWindow->setFrame(Rect{100, 100, 200, 200});
4339 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004340 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4341 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004342 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004343 mDispatcher->onWindowInfosChanged(
4344 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004345
4346 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004347 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4348 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4349 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004350 window->assertNoEvents();
4351 secondWindow->assertNoEvents();
4352
4353 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4354 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004355 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4356 ADISPLAY_ID_DEFAULT,
4357 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004358 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4359 window->consumeMotionEvent(
4360 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004361 secondWindow->consumeMotionDown();
4362 thirdWindow->assertNoEvents();
4363
4364 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4365 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004366 mDispatcher->notifyMotion(
4367 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4368 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004369 window->assertNoEvents();
4370 secondWindow->consumeMotionMove();
4371 thirdWindow->consumeMotionDown();
4372}
4373
Prabir Pradhan814fe082022-07-22 20:22:18 +00004374TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004376 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4377 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004378 window->setFocusable(true);
4379
Patrick Williamsd828f302023-04-28 17:52:08 -05004380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004381 setFocusedWindow(window);
4382
4383 window->consumeFocusEvent(true);
4384
Prabir Pradhan678438e2023-04-13 19:32:51 +00004385 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4386 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4387 mDispatcher->notifyKey(keyDown);
4388 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004389
4390 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4391 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4392
4393 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004394 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004395
4396 window->consumeFocusEvent(false);
4397
Prabir Pradhan678438e2023-04-13 19:32:51 +00004398 mDispatcher->notifyKey(keyDown);
4399 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004400 window->assertNoEvents();
4401}
4402
Arthur Hung96483742022-11-15 03:30:48 +00004403TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4405 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4406 "Fake Window", ADISPLAY_ID_DEFAULT);
4407 // Ensure window is non-split and have some transform.
4408 window->setPreventSplitting(true);
4409 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004410 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004411
4412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004413 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004414 {50, 50}))
4415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4416 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4417
4418 const MotionEvent secondFingerDownEvent =
4419 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4420 .displayId(ADISPLAY_ID_DEFAULT)
4421 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004422 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4423 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004424 .build();
4425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004426 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004427 InputEventInjectionSync::WAIT_FOR_RESULT))
4428 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4429
4430 const MotionEvent* event = window->consumeMotion();
4431 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4432 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4433 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4434 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4435 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4436}
4437
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004438/**
4439 * Two windows: a splittable and a non-splittable.
4440 * The non-splittable window shouldn't receive any "incomplete" gestures.
4441 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4442 * The second pointer should be dropped because the initial window is splittable, so it won't get
4443 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4444 * "incomplete" gestures.
4445 */
4446TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4448 sp<FakeWindowHandle> leftWindow =
4449 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4450 ADISPLAY_ID_DEFAULT);
4451 leftWindow->setPreventSplitting(false);
4452 leftWindow->setFrame(Rect(0, 0, 100, 100));
4453 sp<FakeWindowHandle> rightWindow =
4454 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4455 ADISPLAY_ID_DEFAULT);
4456 rightWindow->setPreventSplitting(true);
4457 rightWindow->setFrame(Rect(100, 100, 200, 200));
4458 mDispatcher->onWindowInfosChanged(
4459 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4460
4461 // Touch down on left, splittable window
4462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4463 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4464 .build());
4465 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4466
4467 mDispatcher->notifyMotion(
4468 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4469 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4470 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4471 .build());
4472 leftWindow->assertNoEvents();
4473 rightWindow->assertNoEvents();
4474}
4475
Harry Cuttsb166c002023-05-09 13:06:05 +00004476TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4478 sp<FakeWindowHandle> window =
4479 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4480 window->setFrame(Rect(0, 0, 400, 400));
4481 sp<FakeWindowHandle> trustedOverlay =
4482 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4483 ADISPLAY_ID_DEFAULT);
4484 trustedOverlay->setSpy(true);
4485 trustedOverlay->setTrustedOverlay(true);
4486
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004487 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004488
4489 // Start a three-finger touchpad swipe
4490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4491 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4492 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4493 .build());
4494 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4495 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4496 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4497 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4498 .build());
4499 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4500 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4501 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4502 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4503 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4504 .build());
4505
4506 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4507 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4508 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4509
4510 // Move the swipe a bit
4511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4512 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4513 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4514 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4515 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4516 .build());
4517
4518 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4519
4520 // End the swipe
4521 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4522 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4523 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4524 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4525 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4526 .build());
4527 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4528 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4529 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4530 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4531 .build());
4532 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4533 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4534 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4535 .build());
4536
4537 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4538 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4539 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4540
4541 window->assertNoEvents();
4542}
4543
4544TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4546 sp<FakeWindowHandle> window =
4547 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4548 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004549 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004550
4551 // Start a three-finger touchpad swipe
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4553 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4554 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4555 .build());
4556 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4557 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4558 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4559 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4560 .build());
4561 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4562 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4563 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4564 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4565 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4566 .build());
4567
4568 // Move the swipe a bit
4569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4570 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4571 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4572 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4573 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4574 .build());
4575
4576 // End the swipe
4577 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4578 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4579 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4580 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4581 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4582 .build());
4583 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4584 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4585 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4586 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4587 .build());
4588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4589 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4590 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4591 .build());
4592
4593 window->assertNoEvents();
4594}
4595
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004596/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004597 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4598 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004599 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004600 */
4601TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4603 sp<FakeWindowHandle> window =
4604 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4605 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004606 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004607
4608 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4610 .downTime(baseTime + 10)
4611 .eventTime(baseTime + 10)
4612 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4613 .build());
4614
4615 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4616
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004617 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004618 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004619
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004620 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004621
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004622 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4623 .downTime(baseTime + 10)
4624 .eventTime(baseTime + 30)
4625 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4626 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4627 .build());
4628
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004629 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4630
4631 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004632 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4633 .downTime(baseTime + 10)
4634 .eventTime(baseTime + 40)
4635 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4636 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4637 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004638
4639 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4640
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4642 .downTime(baseTime + 10)
4643 .eventTime(baseTime + 50)
4644 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4645 .build());
4646
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004647 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4648
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4650 .downTime(baseTime + 60)
4651 .eventTime(baseTime + 60)
4652 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4653 .build());
4654
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004655 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004656}
4657
4658/**
Hu Guo771a7692023-09-17 20:51:08 +08004659 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4660 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4661 * its coordinates should be converted by the transform of the windows of target screen.
4662 */
4663TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4664 // This case will create a window and a spy window on the default display and mirror
4665 // window on the second display. cancel event is sent through spy window pilferPointers
4666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4667
4668 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4669 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4670 spyWindowDefaultDisplay->setTrustedOverlay(true);
4671 spyWindowDefaultDisplay->setSpy(true);
4672
4673 sp<FakeWindowHandle> windowDefaultDisplay =
4674 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4675 ADISPLAY_ID_DEFAULT);
4676 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4677
4678 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4679 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4680
4681 // Add the windows to the dispatcher
4682 mDispatcher->onWindowInfosChanged(
4683 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4684 *windowSecondDisplay->getInfo()},
4685 {},
4686 0,
4687 0});
4688
4689 // Send down to ADISPLAY_ID_DEFAULT
4690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4692 {100, 100}))
4693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4694
4695 spyWindowDefaultDisplay->consumeMotionDown();
4696 windowDefaultDisplay->consumeMotionDown();
4697
4698 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4699
4700 // windowDefaultDisplay gets cancel
4701 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4702 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4703
4704 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4705 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4706 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4707 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4708 EXPECT_EQ(100, event->getX(0));
4709 EXPECT_EQ(100, event->getY(0));
4710}
4711
4712/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004713 * Ensure the correct coordinate spaces are used by InputDispatcher.
4714 *
4715 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4716 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4717 * space.
4718 */
4719class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4720public:
4721 void SetUp() override {
4722 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004723 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004724 }
4725
4726 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4727 gui::DisplayInfo info;
4728 info.displayId = displayId;
4729 info.transform = transform;
4730 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004731 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004732 }
4733
4734 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4735 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004736 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004737 }
4738
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004739 void removeAllWindowsAndDisplays() {
4740 mDisplayInfos.clear();
4741 mWindowInfos.clear();
4742 }
4743
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004744 // Set up a test scenario where the display has a scaled projection and there are two windows
4745 // on the display.
4746 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4747 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4748 // respectively.
4749 ui::Transform displayTransform;
4750 displayTransform.set(2, 0, 0, 4);
4751 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4752
4753 std::shared_ptr<FakeApplicationHandle> application =
4754 std::make_shared<FakeApplicationHandle>();
4755
4756 // Add two windows to the display. Their frames are represented in the display space.
4757 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004758 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4759 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004760 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4761 addWindow(firstWindow);
4762
4763 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004764 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4765 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004766 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4767 addWindow(secondWindow);
4768 return {std::move(firstWindow), std::move(secondWindow)};
4769 }
4770
4771private:
4772 std::vector<gui::DisplayInfo> mDisplayInfos;
4773 std::vector<gui::WindowInfo> mWindowInfos;
4774};
4775
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004776TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004777 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4778 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004779 // selected so that if the hit test was performed with the point and the bounds being in
4780 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004781 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4782 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4783 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004784
4785 firstWindow->consumeMotionDown();
4786 secondWindow->assertNoEvents();
4787}
4788
4789// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4790// the event should be treated as being in the logical display space.
4791TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4792 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4793 // Send down to the first window. The point is represented in the logical display space. The
4794 // point is selected so that if the hit test was done in logical display space, then it would
4795 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004796 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004797 PointF{75 * 2, 55 * 4});
4798
4799 firstWindow->consumeMotionDown();
4800 secondWindow->assertNoEvents();
4801}
4802
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004803// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4804// event should be treated as being in the logical display space.
4805TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4806 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4807
4808 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4809 ui::Transform injectedEventTransform;
4810 injectedEventTransform.set(matrix);
4811 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4812 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4813
4814 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4815 .displayId(ADISPLAY_ID_DEFAULT)
4816 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004817 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004818 .x(untransformedPoint.x)
4819 .y(untransformedPoint.y))
4820 .build();
4821 event.transform(matrix);
4822
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004823 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004824 InputEventInjectionSync::WAIT_FOR_RESULT);
4825
4826 firstWindow->consumeMotionDown();
4827 secondWindow->assertNoEvents();
4828}
4829
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004830TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4831 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4832
4833 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004834 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4835 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4836 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004837
4838 firstWindow->assertNoEvents();
4839 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004840 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004841 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4842
4843 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4844 EXPECT_EQ(300, event->getRawX(0));
4845 EXPECT_EQ(880, event->getRawY(0));
4846
4847 // Ensure that the x and y values are in the window's coordinate space.
4848 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4849 // the logical display space. This will be the origin of the window space.
4850 EXPECT_EQ(100, event->getX(0));
4851 EXPECT_EQ(80, event->getY(0));
4852}
4853
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004854TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4855 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4856 // The monitor will always receive events in the logical display's coordinate space, because
4857 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004858 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004859
4860 // Send down to the first window.
4861 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4862 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4863 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4864 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4865
4866 // Second pointer goes down on second window.
4867 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4868 ADISPLAY_ID_DEFAULT,
4869 {PointF{50, 100}, PointF{150, 220}}));
4870 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4871 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4872 {1, PointF{300, 880}}};
4873 monitor.consumeMotionEvent(
4874 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4875
4876 mDispatcher->cancelCurrentTouch();
4877
4878 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4879 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4880 monitor.consumeMotionEvent(
4881 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4882}
4883
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004884TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4885 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4886
4887 // Send down to the first window.
4888 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4889 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4890 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4891
4892 // The pointer is transferred to the second window, and the second window receives it in the
4893 // correct coordinate space.
4894 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4895 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4896 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4897}
4898
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004899TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4900 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4901
4902 // Send hover move to the second window, and ensure it shows up as hover enter.
4903 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4904 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4905 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4906 WithCoords(100, 80), WithRawCoords(300, 880)));
4907
4908 // Touch down at the same location and ensure a hover exit is synthesized.
4909 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4910 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4911 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4912 WithRawCoords(300, 880)));
4913 secondWindow->consumeMotionEvent(
4914 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4915 secondWindow->assertNoEvents();
4916 firstWindow->assertNoEvents();
4917}
4918
Prabir Pradhan453ae732023-10-13 14:30:14 +00004919// Same as above, but while the window is being mirrored.
4920TEST_F(InputDispatcherDisplayProjectionTest,
4921 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4922 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4923
4924 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4925 ui::Transform secondDisplayTransform;
4926 secondDisplayTransform.set(matrix);
4927 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4928
4929 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4930 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4931 addWindow(secondWindowClone);
4932
4933 // Send hover move to the second window, and ensure it shows up as hover enter.
4934 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4935 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4936 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4937 WithCoords(100, 80), WithRawCoords(300, 880)));
4938
4939 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4940 // display.
4941 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4942 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4943 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4944 WithRawCoords(300, 880)));
4945 secondWindow->consumeMotionEvent(
4946 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4947 secondWindow->assertNoEvents();
4948 firstWindow->assertNoEvents();
4949}
4950
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004951TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4952 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4953
4954 // Send hover enter to second window
4955 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4956 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4957 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4958 WithCoords(100, 80), WithRawCoords(300, 880)));
4959
4960 mDispatcher->cancelCurrentTouch();
4961
4962 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4963 WithRawCoords(300, 880)));
4964 secondWindow->assertNoEvents();
4965 firstWindow->assertNoEvents();
4966}
4967
Prabir Pradhan453ae732023-10-13 14:30:14 +00004968// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004969TEST_F(InputDispatcherDisplayProjectionTest,
4970 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4971 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4972
4973 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4974 ui::Transform secondDisplayTransform;
4975 secondDisplayTransform.set(matrix);
4976 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4977
4978 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4979 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4980 addWindow(secondWindowClone);
4981
4982 // Send hover enter to second window
4983 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4984 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4985 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4986 WithCoords(100, 80), WithRawCoords(300, 880),
4987 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4988
4989 mDispatcher->cancelCurrentTouch();
4990
4991 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4992 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4993 WithRawCoords(300, 880),
4994 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4995 secondWindow->assertNoEvents();
4996 firstWindow->assertNoEvents();
4997}
4998
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004999/** Ensure consistent behavior of InputDispatcher in all orientations. */
5000class InputDispatcherDisplayOrientationFixture
5001 : public InputDispatcherDisplayProjectionTest,
5002 public ::testing::WithParamInterface<ui::Rotation> {};
5003
5004// This test verifies the touchable region of a window for all rotations of the display by tapping
5005// in different locations on the display, specifically points close to the four corners of a
5006// window.
5007TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5008 constexpr static int32_t displayWidth = 400;
5009 constexpr static int32_t displayHeight = 800;
5010
5011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5012
5013 const auto rotation = GetParam();
5014
5015 // Set up the display with the specified rotation.
5016 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5017 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5018 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5019 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5020 logicalDisplayWidth, logicalDisplayHeight);
5021 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5022
5023 // Create a window with its bounds determined in the logical display.
5024 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5025 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5026 sp<FakeWindowHandle> window =
5027 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5028 window->setFrame(frameInDisplay, displayTransform);
5029 addWindow(window);
5030
5031 // The following points in logical display space should be inside the window.
5032 static const std::array<vec2, 4> insidePoints{
5033 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5034 for (const auto pointInsideWindow : insidePoints) {
5035 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5036 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005037 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5039 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005040 window->consumeMotionDown();
5041
Prabir Pradhan678438e2023-04-13 19:32:51 +00005042 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5043 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5044 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005045 window->consumeMotionUp();
5046 }
5047
5048 // The following points in logical display space should be outside the window.
5049 static const std::array<vec2, 5> outsidePoints{
5050 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5051 for (const auto pointOutsideWindow : outsidePoints) {
5052 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5053 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005054 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5055 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5056 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005057
Prabir Pradhan678438e2023-04-13 19:32:51 +00005058 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5059 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5060 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005061 }
5062 window->assertNoEvents();
5063}
5064
5065// Run the precision tests for all rotations.
5066INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5067 InputDispatcherDisplayOrientationFixture,
5068 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5069 ui::ROTATION_270),
5070 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5071 return ftl::enum_string(testParamInfo.param);
5072 });
5073
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005074using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5075 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005076
5077class TransferTouchFixture : public InputDispatcherTest,
5078 public ::testing::WithParamInterface<TransferFunction> {};
5079
5080TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005082
5083 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005084 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005085 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5086 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005087 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005088 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005089 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5090 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005091 sp<FakeWindowHandle> wallpaper =
5092 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5093 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005094 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005095 mDispatcher->onWindowInfosChanged(
5096 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005097
5098 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005099 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5100 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005101
Svet Ganov5d3bc372020-01-26 23:11:07 -08005102 // Only the first window should get the down event
5103 firstWindow->consumeMotionDown();
5104 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005105 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005106
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005107 // Transfer touch to the second window
5108 TransferFunction f = GetParam();
5109 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5110 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005111 // The first window gets cancel and the second gets down
5112 firstWindow->consumeMotionCancel();
5113 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005114 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005115
5116 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005117 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5118 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005119 // The first window gets no events and the second gets up
5120 firstWindow->assertNoEvents();
5121 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005122 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005123}
5124
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005125/**
5126 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5127 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5128 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5129 * natural to the user.
5130 * In this test, we are sending a pointer to both spy window and first window. We then try to
5131 * transfer touch to the second window. The dispatcher should identify the first window as the
5132 * one that should lose the gesture, and therefore the action should be to move the gesture from
5133 * the first window to the second.
5134 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5135 * the other API, as well.
5136 */
5137TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5138 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5139
5140 // Create a couple of windows + a spy window
5141 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005142 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005143 spyWindow->setTrustedOverlay(true);
5144 spyWindow->setSpy(true);
5145 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005146 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005147 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005148 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005149
5150 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005151 mDispatcher->onWindowInfosChanged(
5152 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005153
5154 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5156 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005157 // Only the first window and spy should get the down event
5158 spyWindow->consumeMotionDown();
5159 firstWindow->consumeMotionDown();
5160
5161 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5162 // if f === 'transferTouch'.
5163 TransferFunction f = GetParam();
5164 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5165 ASSERT_TRUE(success);
5166 // The first window gets cancel and the second gets down
5167 firstWindow->consumeMotionCancel();
5168 secondWindow->consumeMotionDown();
5169
5170 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005171 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5172 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005173 // The first window gets no events and the second+spy get up
5174 firstWindow->assertNoEvents();
5175 spyWindow->consumeMotionUp();
5176 secondWindow->consumeMotionUp();
5177}
5178
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005179TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005181
5182 PointF touchPoint = {10, 10};
5183
5184 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005185 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005186 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5187 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005188 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005189 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005190 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5191 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005192 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005193
5194 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005195 mDispatcher->onWindowInfosChanged(
5196 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005197
5198 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005199 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5200 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5201 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005202 // Only the first window should get the down event
5203 firstWindow->consumeMotionDown();
5204 secondWindow->assertNoEvents();
5205
5206 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005207 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5208 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005209 // Only the first window should get the pointer down event
5210 firstWindow->consumeMotionPointerDown(1);
5211 secondWindow->assertNoEvents();
5212
5213 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005214 TransferFunction f = GetParam();
5215 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5216 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005217 // The first window gets cancel and the second gets down and pointer down
5218 firstWindow->consumeMotionCancel();
5219 secondWindow->consumeMotionDown();
5220 secondWindow->consumeMotionPointerDown(1);
5221
5222 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005223 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5224 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005225 // The first window gets nothing and the second gets pointer up
5226 firstWindow->assertNoEvents();
5227 secondWindow->consumeMotionPointerUp(1);
5228
5229 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005230 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5231 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005232 // The first window gets nothing and the second gets up
5233 firstWindow->assertNoEvents();
5234 secondWindow->consumeMotionUp();
5235}
5236
Arthur Hungc539dbb2022-12-08 07:45:36 +00005237TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5239
5240 // Create a couple of windows
5241 sp<FakeWindowHandle> firstWindow =
5242 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5243 ADISPLAY_ID_DEFAULT);
5244 firstWindow->setDupTouchToWallpaper(true);
5245 sp<FakeWindowHandle> secondWindow =
5246 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5247 ADISPLAY_ID_DEFAULT);
5248 secondWindow->setDupTouchToWallpaper(true);
5249
5250 sp<FakeWindowHandle> wallpaper1 =
5251 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5252 wallpaper1->setIsWallpaper(true);
5253
5254 sp<FakeWindowHandle> wallpaper2 =
5255 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5256 wallpaper2->setIsWallpaper(true);
5257 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005258 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5259 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5260 {},
5261 0,
5262 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005263
5264 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5266 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005267
5268 // Only the first window should get the down event
5269 firstWindow->consumeMotionDown();
5270 secondWindow->assertNoEvents();
5271 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5272 wallpaper2->assertNoEvents();
5273
5274 // Transfer touch focus to the second window
5275 TransferFunction f = GetParam();
5276 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5277 ASSERT_TRUE(success);
5278
5279 // The first window gets cancel and the second gets down
5280 firstWindow->consumeMotionCancel();
5281 secondWindow->consumeMotionDown();
5282 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5283 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5284
5285 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005286 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5287 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005288 // The first window gets no events and the second gets up
5289 firstWindow->assertNoEvents();
5290 secondWindow->consumeMotionUp();
5291 wallpaper1->assertNoEvents();
5292 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5293}
5294
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005295// For the cases of single pointer touch and two pointers non-split touch, the api's
5296// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5297// for the case where there are multiple pointers split across several windows.
5298INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5299 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005300 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5301 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005302 return dispatcher->transferTouch(destChannelToken,
5303 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005304 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005305 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5306 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005307 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005308 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005309 }));
5310
Svet Ganov5d3bc372020-01-26 23:11:07 -08005311TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005313
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005314 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005315 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5316 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005317 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005318
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005319 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005320 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5321 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005322 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005323
5324 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005325 mDispatcher->onWindowInfosChanged(
5326 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005327
5328 PointF pointInFirst = {300, 200};
5329 PointF pointInSecond = {300, 600};
5330
5331 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005332 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5333 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5334 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005335 // Only the first window should get the down event
5336 firstWindow->consumeMotionDown();
5337 secondWindow->assertNoEvents();
5338
5339 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005340 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5341 ADISPLAY_ID_DEFAULT,
5342 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005343 // The first window gets a move and the second a down
5344 firstWindow->consumeMotionMove();
5345 secondWindow->consumeMotionDown();
5346
5347 // Transfer touch focus to the second window
5348 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5349 // The first window gets cancel and the new gets pointer down (it already saw down)
5350 firstWindow->consumeMotionCancel();
5351 secondWindow->consumeMotionPointerDown(1);
5352
5353 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005354 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5355 ADISPLAY_ID_DEFAULT,
5356 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005357 // The first window gets nothing and the second gets pointer up
5358 firstWindow->assertNoEvents();
5359 secondWindow->consumeMotionPointerUp(1);
5360
5361 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005362 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5363 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005364 // The first window gets nothing and the second gets up
5365 firstWindow->assertNoEvents();
5366 secondWindow->consumeMotionUp();
5367}
5368
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005369// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5370// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5371// touch is not supported, so the touch should continue on those windows and the transferred-to
5372// window should get nothing.
5373TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5375
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005376 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005377 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5378 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005379 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005380
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005381 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005382 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5383 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005384 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005385
5386 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005387 mDispatcher->onWindowInfosChanged(
5388 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005389
5390 PointF pointInFirst = {300, 200};
5391 PointF pointInSecond = {300, 600};
5392
5393 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5395 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5396 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005397 // Only the first window should get the down event
5398 firstWindow->consumeMotionDown();
5399 secondWindow->assertNoEvents();
5400
5401 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005402 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5403 ADISPLAY_ID_DEFAULT,
5404 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005405 // The first window gets a move and the second a down
5406 firstWindow->consumeMotionMove();
5407 secondWindow->consumeMotionDown();
5408
5409 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005410 const bool transferred =
5411 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005412 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5413 ASSERT_FALSE(transferred);
5414 firstWindow->assertNoEvents();
5415 secondWindow->assertNoEvents();
5416
5417 // The rest of the dispatch should proceed as normal
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,
5421 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005422 // The first window gets MOVE and the second gets pointer up
5423 firstWindow->consumeMotionMove();
5424 secondWindow->consumeMotionUp();
5425
5426 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005427 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5428 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005429 // The first window gets nothing and the second gets up
5430 firstWindow->consumeMotionUp();
5431 secondWindow->assertNoEvents();
5432}
5433
Arthur Hungabbb9d82021-09-01 14:52:30 +00005434// This case will create two windows and one mirrored window on the default display and mirror
5435// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5436// the windows info of second display before default display.
5437TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5439 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005440 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005441 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005442 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005443 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005444 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005445
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005446 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005447 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005448
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005449 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005450 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005451
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005452 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005453 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005454
5455 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005456 mDispatcher->onWindowInfosChanged(
5457 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5458 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5459 *secondWindowInPrimary->getInfo()},
5460 {},
5461 0,
5462 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005463
5464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005466 {50, 50}))
5467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5468
5469 // Window should receive motion event.
5470 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5471
5472 // Transfer touch focus
5473 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5474 secondWindowInPrimary->getToken()));
5475 // The first window gets cancel.
5476 firstWindowInPrimary->consumeMotionCancel();
5477 secondWindowInPrimary->consumeMotionDown();
5478
5479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005480 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005481 ADISPLAY_ID_DEFAULT, {150, 50}))
5482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5483 firstWindowInPrimary->assertNoEvents();
5484 secondWindowInPrimary->consumeMotionMove();
5485
5486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005487 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005488 {150, 50}))
5489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5490 firstWindowInPrimary->assertNoEvents();
5491 secondWindowInPrimary->consumeMotionUp();
5492}
5493
5494// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5495// 'transferTouch' api.
5496TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5497 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5498 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005499 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005500 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005501 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005502 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005503 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005504
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005505 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005506 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005507
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005508 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005509 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005510
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005511 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005513
5514 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005515 mDispatcher->onWindowInfosChanged(
5516 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5517 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5518 *secondWindowInPrimary->getInfo()},
5519 {},
5520 0,
5521 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005522
5523 // Touch on second display.
5524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005525 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5526 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5528
5529 // Window should receive motion event.
5530 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5531
5532 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005533 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005534
5535 // The first window gets cancel.
5536 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5537 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5538
5539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005540 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005541 SECOND_DISPLAY_ID, {150, 50}))
5542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5543 firstWindowInPrimary->assertNoEvents();
5544 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5545
5546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005547 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5549 firstWindowInPrimary->assertNoEvents();
5550 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5551}
5552
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005553TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5556 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005557
Vishnu Nair47074b82020-08-14 11:54:47 -07005558 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005559 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005560 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005561
5562 window->consumeFocusEvent(true);
5563
Prabir Pradhan678438e2023-04-13 19:32:51 +00005564 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005565
5566 // Window should receive key down event.
5567 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005568
5569 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005570 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005571 mFakePolicy->assertUserActivityPoked();
5572}
5573
5574TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5576 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5577 "Fake Window", ADISPLAY_ID_DEFAULT);
5578
5579 window->setDisableUserActivity(true);
5580 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005581 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005582 setFocusedWindow(window);
5583
5584 window->consumeFocusEvent(true);
5585
5586 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5587
5588 // Window should receive key down event.
5589 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5590
5591 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005592 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005593 mFakePolicy->assertUserActivityNotPoked();
5594}
5595
5596TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5598 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5599 "Fake Window", ADISPLAY_ID_DEFAULT);
5600
5601 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005602 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005603 setFocusedWindow(window);
5604
5605 window->consumeFocusEvent(true);
5606
5607 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5608 mDispatcher->waitForIdle();
5609
5610 // System key is not passed down
5611 window->assertNoEvents();
5612
5613 // Should have poked user activity
5614 mFakePolicy->assertUserActivityPoked();
5615}
5616
5617TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5619 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5620 "Fake Window", ADISPLAY_ID_DEFAULT);
5621
5622 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005623 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005624 setFocusedWindow(window);
5625
5626 window->consumeFocusEvent(true);
5627
5628 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5629 mDispatcher->waitForIdle();
5630
5631 // System key is not passed down
5632 window->assertNoEvents();
5633
5634 // Should have poked user activity
5635 mFakePolicy->assertUserActivityPoked();
5636}
5637
5638TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5640 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5641 "Fake Window", ADISPLAY_ID_DEFAULT);
5642
5643 window->setDisableUserActivity(true);
5644 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005645 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005646 setFocusedWindow(window);
5647
5648 window->consumeFocusEvent(true);
5649
5650 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5651 mDispatcher->waitForIdle();
5652
5653 // System key is not passed down
5654 window->assertNoEvents();
5655
5656 // Should have poked user activity
5657 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005658}
5659
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005660TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5662 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5663 "Fake Window", ADISPLAY_ID_DEFAULT);
5664
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005665 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005666
5667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005668 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005669 ADISPLAY_ID_DEFAULT, {100, 100}))
5670 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5671
5672 window->consumeMotionEvent(
5673 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5674
5675 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005676 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005677 mFakePolicy->assertUserActivityPoked();
5678}
5679
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005680TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005682 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5683 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005684
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005686
Prabir Pradhan678438e2023-04-13 19:32:51 +00005687 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005688 mDispatcher->waitForIdle();
5689
5690 window->assertNoEvents();
5691}
5692
5693// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5694TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005695 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005696 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5697 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005698
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005699 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005700
5701 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005702 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005703 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005704 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5705 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005706
5707 // Window should receive only the motion event
5708 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5709 window->assertNoEvents(); // Key event or focus event will not be received
5710}
5711
arthurhungea3f4fc2020-12-21 23:18:53 +08005712TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5714
arthurhungea3f4fc2020-12-21 23:18:53 +08005715 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005716 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5717 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005718 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005719
arthurhungea3f4fc2020-12-21 23:18:53 +08005720 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005721 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5722 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005723 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005724
5725 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005726 mDispatcher->onWindowInfosChanged(
5727 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005728
5729 PointF pointInFirst = {300, 200};
5730 PointF pointInSecond = {300, 600};
5731
5732 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005733 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5734 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5735 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005736 // Only the first window should get the down event
5737 firstWindow->consumeMotionDown();
5738 secondWindow->assertNoEvents();
5739
5740 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005741 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5742 ADISPLAY_ID_DEFAULT,
5743 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005744 // The first window gets a move and the second a down
5745 firstWindow->consumeMotionMove();
5746 secondWindow->consumeMotionDown();
5747
5748 // Send pointer cancel to the second window
5749 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005750 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005751 {pointInFirst, pointInSecond});
5752 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005753 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005754 // The first window gets move and the second gets cancel.
5755 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5756 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5757
5758 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005759 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5760 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005761 // The first window gets up and the second gets nothing.
5762 firstWindow->consumeMotionUp();
5763 secondWindow->assertNoEvents();
5764}
5765
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005766TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5768
5769 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005770 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005771 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005772 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5773 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5774 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5775
Harry Cutts33476232023-01-30 19:57:29 +00005776 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005777 window->assertNoEvents();
5778 mDispatcher->waitForIdle();
5779}
5780
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005781using InputDispatcherMonitorTest = InputDispatcherTest;
5782
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005783/**
5784 * Two entities that receive touch: A window, and a global monitor.
5785 * The touch goes to the window, and then the window disappears.
5786 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5787 * for the monitor, as well.
5788 * 1. foregroundWindow
5789 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5790 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005791TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5793 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005794 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005795
Prabir Pradhanfb549072023-10-05 19:17:36 +00005796 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005797
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005800 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005801 {100, 200}))
5802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5803
5804 // Both the foreground window and the global monitor should receive the touch down
5805 window->consumeMotionDown();
5806 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5807
5808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005809 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005810 ADISPLAY_ID_DEFAULT, {110, 200}))
5811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5812
5813 window->consumeMotionMove();
5814 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5815
5816 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005817 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005818 window->consumeMotionCancel();
5819 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5820
5821 // If more events come in, there will be no more foreground window to send them to. This will
5822 // cause a cancel for the monitor, as well.
5823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005824 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005825 ADISPLAY_ID_DEFAULT, {120, 200}))
5826 << "Injection should fail because the window was removed";
5827 window->assertNoEvents();
5828 // Global monitor now gets the cancel
5829 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5830}
5831
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005832TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005834 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5835 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005837
Prabir Pradhanfb549072023-10-05 19:17:36 +00005838 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005839
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005841 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005843 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005844 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005845}
5846
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005847TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005848 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005849
Chris Yea209fde2020-07-22 13:54:51 -07005850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005851 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5852 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005853 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005854
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005856 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005858 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005859 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005860
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005861 // Pilfer pointers from the monitor.
5862 // This should not do anything and the window should continue to receive events.
5863 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005864
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005866 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005867 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005869
5870 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5871 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005872}
5873
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005874TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005876 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5877 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005878 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005879 window->setWindowOffset(20, 40);
5880 window->setWindowTransform(0, 1, -1, 0);
5881
Prabir Pradhanfb549072023-10-05 19:17:36 +00005882 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005883
5884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005885 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5887 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5888 MotionEvent* event = monitor.consumeMotion();
5889 // Even though window has transform, gesture monitor must not.
5890 ASSERT_EQ(ui::Transform(), event->getTransform());
5891}
5892
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005893TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005895 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005896
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005897 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005898 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005899 << "Injection should fail if there is a monitor, but no touchable window";
5900 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005901}
5902
chaviw81e2bb92019-12-18 15:03:51 -08005903TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005905 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5906 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005907
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005908 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005909
5910 NotifyMotionArgs motionArgs =
5911 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5912 ADISPLAY_ID_DEFAULT);
5913
Prabir Pradhan678438e2023-04-13 19:32:51 +00005914 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005915 // Window should receive motion down event.
5916 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5917
5918 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005919 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005920 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5921 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5922 motionArgs.pointerCoords[0].getX() - 10);
5923
Prabir Pradhan678438e2023-04-13 19:32:51 +00005924 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005925 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005926 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005927}
5928
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005929/**
5930 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5931 * the device default right away. In the test scenario, we check both the default value,
5932 * and the action of enabling / disabling.
5933 */
5934TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005936 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5937 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005938 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005939
5940 // Set focused application.
5941 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005942 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005943
5944 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005945 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005946 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005947 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005948
5949 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005950 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005951 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005952 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005953
5954 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005955 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005956 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005957 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005958 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005959 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005960 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005961 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005962
5963 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005964 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005965 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005966 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005967
5968 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005969 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005970 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005971 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005972 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005973 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005974 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005975 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005976
5977 window->assertNoEvents();
5978}
5979
Gang Wange9087892020-01-07 12:17:14 -05005980TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005982 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5983 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005984
5985 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005986 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005987
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005988 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005989 setFocusedWindow(window);
5990
Harry Cutts33476232023-01-30 19:57:29 +00005991 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005992
Prabir Pradhan678438e2023-04-13 19:32:51 +00005993 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5994 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005995
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005996 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005997 ASSERT_NE(event, nullptr);
5998
5999 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6000 ASSERT_NE(verified, nullptr);
6001 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6002
6003 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6004 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6005 ASSERT_EQ(keyArgs.source, verified->source);
6006 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6007
6008 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6009
6010 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006011 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006012 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006013 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6014 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6015 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6016 ASSERT_EQ(0, verifiedKey.repeatCount);
6017}
6018
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006019TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6022 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006023
6024 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6025
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006026 ui::Transform transform;
6027 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6028
6029 gui::DisplayInfo displayInfo;
6030 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6031 displayInfo.transform = transform;
6032
Patrick Williamsd828f302023-04-28 17:52:08 -05006033 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006034
Prabir Pradhan678438e2023-04-13 19:32:51 +00006035 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006036 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6037 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006038 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006039
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006040 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006041 ASSERT_NE(event, nullptr);
6042
6043 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6044 ASSERT_NE(verified, nullptr);
6045 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6046
6047 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6048 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6049 EXPECT_EQ(motionArgs.source, verified->source);
6050 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6051
6052 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6053
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006054 const vec2 rawXY =
6055 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6056 motionArgs.pointerCoords[0].getXYValue());
6057 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6058 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006059 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006060 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006061 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006062 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6063 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6064}
6065
chaviw09c8d2d2020-08-24 15:48:26 -07006066/**
6067 * Ensure that separate calls to sign the same data are generating the same key.
6068 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6069 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6070 * tests.
6071 */
6072TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6073 KeyEvent event = getTestKeyEvent();
6074 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6075
6076 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6077 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6078 ASSERT_EQ(hmac1, hmac2);
6079}
6080
6081/**
6082 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6083 */
6084TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6085 KeyEvent event = getTestKeyEvent();
6086 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6087 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6088
6089 verifiedEvent.deviceId += 1;
6090 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6091
6092 verifiedEvent.source += 1;
6093 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6094
6095 verifiedEvent.eventTimeNanos += 1;
6096 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6097
6098 verifiedEvent.displayId += 1;
6099 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6100
6101 verifiedEvent.action += 1;
6102 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6103
6104 verifiedEvent.downTimeNanos += 1;
6105 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6106
6107 verifiedEvent.flags += 1;
6108 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6109
6110 verifiedEvent.keyCode += 1;
6111 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6112
6113 verifiedEvent.scanCode += 1;
6114 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6115
6116 verifiedEvent.metaState += 1;
6117 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6118
6119 verifiedEvent.repeatCount += 1;
6120 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6121}
6122
Vishnu Nair958da932020-08-21 17:12:37 -07006123TEST_F(InputDispatcherTest, SetFocusedWindow) {
6124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6125 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006126 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006127 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006128 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006129 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6130
6131 // Top window is also focusable but is not granted focus.
6132 windowTop->setFocusable(true);
6133 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006134 mDispatcher->onWindowInfosChanged(
6135 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006136 setFocusedWindow(windowSecond);
6137
6138 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006140 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006141
6142 // Focused window should receive event.
6143 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6144 windowTop->assertNoEvents();
6145}
6146
6147TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6149 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006150 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006151 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6152
6153 window->setFocusable(true);
6154 // Release channel for window is no longer valid.
6155 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006156 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006157 setFocusedWindow(window);
6158
6159 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006160 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006161
6162 // window channel is invalid, so it should not receive any input event.
6163 window->assertNoEvents();
6164}
6165
6166TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6168 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006169 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006170 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006173 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006174 setFocusedWindow(window);
6175
6176 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006177 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006178
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006179 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006180 window->assertNoEvents();
6181}
6182
6183TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6185 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006186 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006187 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006188 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006189 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6190
6191 windowTop->setFocusable(true);
6192 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006193 mDispatcher->onWindowInfosChanged(
6194 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006195 setFocusedWindow(windowTop);
6196 windowTop->consumeFocusEvent(true);
6197
Chavi Weingarten847e8512023-03-29 00:26:09 +00006198 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006199 mDispatcher->onWindowInfosChanged(
6200 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006201 windowSecond->consumeFocusEvent(true);
6202 windowTop->consumeFocusEvent(false);
6203
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006205 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006206
6207 // Focused window should receive event.
6208 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6209}
6210
Chavi Weingarten847e8512023-03-29 00:26:09 +00006211TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6213 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006214 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006215 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006216 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6218
6219 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006220 windowSecond->setFocusable(false);
6221 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006222 mDispatcher->onWindowInfosChanged(
6223 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006224 setFocusedWindow(windowTop);
6225 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006226
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006228 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006229
6230 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006231 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006232 windowSecond->assertNoEvents();
6233}
6234
6235TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6236 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6237 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006238 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006239 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006240 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6241 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006242 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6243
6244 window->setFocusable(true);
6245 previousFocusedWindow->setFocusable(true);
6246 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006247 mDispatcher->onWindowInfosChanged(
6248 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006249 setFocusedWindow(previousFocusedWindow);
6250 previousFocusedWindow->consumeFocusEvent(true);
6251
6252 // Requesting focus on invisible window takes focus from currently focused window.
6253 setFocusedWindow(window);
6254 previousFocusedWindow->consumeFocusEvent(false);
6255
6256 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006258 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6259 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006260
6261 // Window does not get focus event or key down.
6262 window->assertNoEvents();
6263
6264 // Window becomes visible.
6265 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006266 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006267
6268 // Window receives focus event.
6269 window->consumeFocusEvent(true);
6270 // Focused window receives key down.
6271 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6272}
6273
Vishnu Nair599f1412021-06-21 10:39:58 -07006274TEST_F(InputDispatcherTest, DisplayRemoved) {
6275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6276 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006277 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006278 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6279
6280 // window is granted focus.
6281 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006282 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006283 setFocusedWindow(window);
6284 window->consumeFocusEvent(true);
6285
6286 // When a display is removed window loses focus.
6287 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6288 window->consumeFocusEvent(false);
6289}
6290
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006291/**
6292 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6293 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6294 * of the 'slipperyEnterWindow'.
6295 *
6296 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6297 * a way so that the touched location is no longer covered by the top window.
6298 *
6299 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6300 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6301 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6302 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6303 * with ACTION_DOWN).
6304 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6305 * window moved itself away from the touched location and had Flag::SLIPPERY.
6306 *
6307 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6308 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6309 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6310 *
6311 * In this test, we ensure that the event received by the bottom window has
6312 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6313 */
6314TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006315 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006316 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006317
6318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6319 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6320
6321 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006322 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006323 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006324 // Make sure this one overlaps the bottom window
6325 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6326 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6327 // one. Windows with the same owner are not considered to be occluding each other.
6328 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6329
6330 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006331 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006332 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6333
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006334 mDispatcher->onWindowInfosChanged(
6335 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006336
6337 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006338 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6339 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6340 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006341 slipperyExitWindow->consumeMotionDown();
6342 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006343 mDispatcher->onWindowInfosChanged(
6344 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006345
Prabir Pradhan678438e2023-04-13 19:32:51 +00006346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6348 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006349
6350 slipperyExitWindow->consumeMotionCancel();
6351
6352 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6353 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6354}
6355
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006356/**
6357 * Two windows, one on the left and another on the right. The left window is slippery. The right
6358 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6359 * touch moves from the left window into the right window, the gesture should continue to go to the
6360 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6361 * reproduces a crash.
6362 */
6363TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6365
6366 sp<FakeWindowHandle> leftSlipperyWindow =
6367 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6368 leftSlipperyWindow->setSlippery(true);
6369 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6370
6371 sp<FakeWindowHandle> rightDropTouchesWindow =
6372 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6373 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6374 rightDropTouchesWindow->setDropInput(true);
6375
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006376 mDispatcher->onWindowInfosChanged(
6377 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006378
6379 // Start touch in the left window
6380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6381 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6382 .build());
6383 leftSlipperyWindow->consumeMotionDown();
6384
6385 // And move it into the right window
6386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6387 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6388 .build());
6389
6390 // Since the right window isn't eligible to receive input, touch does not slip.
6391 // The left window continues to receive the gesture.
6392 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6393 rightDropTouchesWindow->assertNoEvents();
6394}
6395
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006396/**
6397 * A single window is on screen first. Touch is injected into that window. Next, a second window
6398 * appears. Since the first window is slippery, touch will move from the first window to the second.
6399 */
6400TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6401 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6402 sp<FakeWindowHandle> originalWindow =
6403 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6404 originalWindow->setFrame(Rect(0, 0, 200, 200));
6405 originalWindow->setSlippery(true);
6406
6407 sp<FakeWindowHandle> appearingWindow =
6408 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6409 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6410
6411 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6412
6413 // Touch down on the original window
6414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6415 injectMotionEvent(*mDispatcher,
6416 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6417 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6418 .build()));
6419 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6420
6421 // Now, a new window appears. This could be, for example, a notification shade that appears
6422 // after user starts to drag down on the launcher window.
6423 mDispatcher->onWindowInfosChanged(
6424 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6426 injectMotionEvent(*mDispatcher,
6427 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6428 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6429 .build()));
6430 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6431 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6433 injectMotionEvent(*mDispatcher,
6434 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6435 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6436 .build()));
6437 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6438
6439 originalWindow->assertNoEvents();
6440 appearingWindow->assertNoEvents();
6441}
6442
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006443TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006444 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6446
6447 sp<FakeWindowHandle> leftWindow =
6448 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6449 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006450 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006451
6452 sp<FakeWindowHandle> rightSpy =
6453 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6454 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006455 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006456 rightSpy->setSpy(true);
6457 rightSpy->setTrustedOverlay(true);
6458
6459 sp<FakeWindowHandle> rightWindow =
6460 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6461 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006462 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006463
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006464 mDispatcher->onWindowInfosChanged(
6465 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006466
6467 // Touch in the left window
6468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6469 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6470 .build());
6471 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6472 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006473 ASSERT_NO_FATAL_FAILURE(
6474 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006475
6476 // Touch another finger over the right windows
6477 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6478 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6479 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6480 .build());
6481 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6482 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6483 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6484 mDispatcher->waitForIdle();
6485 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006486 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6487 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006488
6489 // Release finger over left window. The UP actions are not treated as device interaction.
6490 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6491 // is part of the UP action, we do not treat this as device interaction.
6492 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6493 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6494 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6495 .build());
6496 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6497 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6498 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6499 mDispatcher->waitForIdle();
6500 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6501
6502 // Move remaining finger
6503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6504 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6505 .build());
6506 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6507 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6508 mDispatcher->waitForIdle();
6509 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006510 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006511
6512 // Release all fingers
6513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6514 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6515 .build());
6516 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6517 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6518 mDispatcher->waitForIdle();
6519 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6520}
6521
6522TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6524
6525 sp<FakeWindowHandle> window =
6526 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6527 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006528 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006530 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006531 setFocusedWindow(window);
6532 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6533
6534 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6535 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6536 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006537 ASSERT_NO_FATAL_FAILURE(
6538 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006539
6540 // The UP actions are not treated as device interaction.
6541 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6542 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6543 mDispatcher->waitForIdle();
6544 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6545}
6546
Prabir Pradhan5893d362023-11-17 04:30:40 +00006547TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6549
6550 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6551 ADISPLAY_ID_DEFAULT);
6552 left->setFrame(Rect(0, 0, 100, 100));
6553 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6554 "Right Window", ADISPLAY_ID_DEFAULT);
6555 right->setFrame(Rect(100, 0, 200, 100));
6556 sp<FakeWindowHandle> spy =
6557 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6558 spy->setFrame(Rect(0, 0, 200, 100));
6559 spy->setTrustedOverlay(true);
6560 spy->setSpy(true);
6561
6562 mDispatcher->onWindowInfosChanged(
6563 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6564
6565 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6566 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6567 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6568 mDispatcher->notifyMotion(notifyArgs);
6569
6570 const MotionEvent& leftEnter = left->consumeMotionEvent(
6571 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6572 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6573
6574 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6575 Not(WithEventId(notifyArgs.id)),
6576 Not(WithEventId(leftEnter.getId())),
6577 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6578
6579 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6580 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6581 {PointF{150, 50}});
6582 mDispatcher->notifyMotion(notifyArgs);
6583
6584 const MotionEvent& leftExit = left->consumeMotionEvent(
6585 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6586 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6587
6588 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6589 Not(WithEventId(notifyArgs.id)),
6590 Not(WithEventId(leftExit.getId())),
6591 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6592
6593 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6594}
6595
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006596class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6597protected:
6598 std::shared_ptr<FakeApplicationHandle> mApp;
6599 sp<FakeWindowHandle> mWindow;
6600
6601 virtual void SetUp() override {
6602 InputDispatcherTest::SetUp();
6603
6604 mApp = std::make_shared<FakeApplicationHandle>();
6605
6606 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6607 mWindow->setFrame(Rect(0, 0, 100, 100));
6608
6609 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6610 setFocusedWindow(mWindow);
6611 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6612 }
6613
6614 void setFallback(int32_t keycode) {
6615 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6616 return KeyEventBuilder(event).keyCode(keycode).build();
6617 });
6618 }
6619
6620 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6621 KeyEvent* event = mWindow->consumeKey(handled);
6622 ASSERT_NE(event, nullptr) << "Did not receive key event";
6623 ASSERT_THAT(*event, matcher);
6624 }
6625};
6626
6627TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6628 mDispatcher->notifyKey(
6629 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6630 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6631 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6632}
6633
6634TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6635 mDispatcher->notifyKey(
6636 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6637 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6638 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6639}
6640
6641TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6642 mDispatcher->notifyKey(
6643 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6644
6645 // Do not handle this key event.
6646 consumeKey(/*handled=*/false,
6647 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6648 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6649
6650 // Since the policy did not request any fallback to be generated, ensure there are no events.
6651 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6652}
6653
6654TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6655 setFallback(AKEYCODE_B);
6656 mDispatcher->notifyKey(
6657 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6658
6659 // Do not handle this key event.
6660 consumeKey(/*handled=*/false,
6661 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6662
6663 // Since the key was not handled, ensure the fallback event was dispatched instead.
6664 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6665 consumeKey(/*handled=*/true,
6666 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6667 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6668
6669 // Release the original key, and ensure the fallback key is also released.
6670 mDispatcher->notifyKey(
6671 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6672 consumeKey(/*handled=*/false,
6673 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6674 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6675 consumeKey(/*handled=*/true,
6676 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6677 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6678
6679 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6680 mWindow->assertNoEvents();
6681}
6682
6683TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6684 setFallback(AKEYCODE_B);
6685 mDispatcher->notifyKey(
6686 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6687
6688 // Do not handle this key event, but handle the fallback.
6689 consumeKey(/*handled=*/false,
6690 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6691 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6692 consumeKey(/*handled=*/true,
6693 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6694 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6695
6696 // Release the original key, and ensure the fallback key is also released.
6697 mDispatcher->notifyKey(
6698 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6699 // But this time, the app handles the original key.
6700 consumeKey(/*handled=*/true,
6701 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6702 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6703 // Ensure the fallback key is canceled.
6704 consumeKey(/*handled=*/true,
6705 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6706 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6707
6708 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6709 mWindow->assertNoEvents();
6710}
6711
6712TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6713 setFallback(AKEYCODE_B);
6714 mDispatcher->notifyKey(
6715 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6716
6717 // Do not handle this key event.
6718 consumeKey(/*handled=*/false,
6719 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6720 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6721 // App does not handle the fallback either, so ensure another fallback is not generated.
6722 setFallback(AKEYCODE_C);
6723 consumeKey(/*handled=*/false,
6724 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6725 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6726
6727 // Release the original key, and ensure the fallback key is also released.
6728 setFallback(AKEYCODE_B);
6729 mDispatcher->notifyKey(
6730 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6731 consumeKey(/*handled=*/false,
6732 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6733 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6734 consumeKey(/*handled=*/false,
6735 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6736 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6737
6738 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6739 mWindow->assertNoEvents();
6740}
6741
6742TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6743 setFallback(AKEYCODE_B);
6744 mDispatcher->notifyKey(
6745 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6746
6747 // Do not handle this key event, so fallback is generated.
6748 consumeKey(/*handled=*/false,
6749 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6750 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6751 consumeKey(/*handled=*/true,
6752 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6753 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6754
6755 // Release the original key, but assume the policy is misbehaving and it
6756 // generates an inconsistent fallback to the one from the DOWN event.
6757 setFallback(AKEYCODE_C);
6758 mDispatcher->notifyKey(
6759 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6760 consumeKey(/*handled=*/false,
6761 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6762 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6763 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6764 consumeKey(/*handled=*/true,
6765 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6766 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6767
6768 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6769 mWindow->assertNoEvents();
6770}
6771
6772TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6773 setFallback(AKEYCODE_B);
6774 mDispatcher->notifyKey(
6775 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6776
6777 // Do not handle this key event, so fallback is generated.
6778 consumeKey(/*handled=*/false,
6779 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6780 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6781 consumeKey(/*handled=*/true,
6782 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6783 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6784
6785 // The original key is canceled.
6786 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6787 .keyCode(AKEYCODE_A)
6788 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6789 .build());
6790 consumeKey(/*handled=*/false,
6791 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6792 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6793 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6794 // Ensure the fallback key is also canceled due to the original key being canceled.
6795 consumeKey(/*handled=*/true,
6796 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6797 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6798
6799 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6800 mWindow->assertNoEvents();
6801}
6802
Garfield Tan1c7bc862020-01-28 13:24:04 -08006803class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6804protected:
6805 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6806 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6807
Chris Yea209fde2020-07-22 13:54:51 -07006808 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006809 sp<FakeWindowHandle> mWindow;
6810
6811 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006812 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006813 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006814 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006815 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006816 ASSERT_EQ(OK, mDispatcher->start());
6817
6818 setUpWindow();
6819 }
6820
6821 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006822 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006823 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006824
Vishnu Nair47074b82020-08-14 11:54:47 -07006825 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006826 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006827 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006828 mWindow->consumeFocusEvent(true);
6829 }
6830
Chris Ye2ad95392020-09-01 13:44:44 -07006831 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006832 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006833 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006834 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006835 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006836
6837 // Window should receive key down event.
6838 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6839 }
6840
6841 void expectKeyRepeatOnce(int32_t repeatCount) {
6842 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006843 mWindow->consumeKeyEvent(
6844 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006845 }
6846
Chris Ye2ad95392020-09-01 13:44:44 -07006847 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006848 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006849 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006850 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006851 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006852
6853 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006854 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006855 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006856 }
6857};
6858
6859TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006860 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006861 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6862 expectKeyRepeatOnce(repeatCount);
6863 }
6864}
6865
6866TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006867 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006868 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6869 expectKeyRepeatOnce(repeatCount);
6870 }
Harry Cutts33476232023-01-30 19:57:29 +00006871 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006872 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006873 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6874 expectKeyRepeatOnce(repeatCount);
6875 }
6876}
6877
6878TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006879 sendAndConsumeKeyDown(/*deviceId=*/1);
6880 expectKeyRepeatOnce(/*repeatCount=*/1);
6881 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006882 mWindow->assertNoEvents();
6883}
6884
6885TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006886 sendAndConsumeKeyDown(/*deviceId=*/1);
6887 expectKeyRepeatOnce(/*repeatCount=*/1);
6888 sendAndConsumeKeyDown(/*deviceId=*/2);
6889 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006890 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006891 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006892 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006893 expectKeyRepeatOnce(/*repeatCount=*/2);
6894 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006895 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006896 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006897 mWindow->assertNoEvents();
6898}
6899
6900TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006901 sendAndConsumeKeyDown(/*deviceId=*/1);
6902 expectKeyRepeatOnce(/*repeatCount=*/1);
6903 sendAndConsumeKeyDown(/*deviceId=*/2);
6904 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006905 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006906 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006907 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006908 mWindow->assertNoEvents();
6909}
6910
liushenxiang42232912021-05-21 20:24:09 +08006911TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6912 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006913 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006914 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006915 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6916 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6917 mWindow->assertNoEvents();
6918}
6919
Garfield Tan1c7bc862020-01-28 13:24:04 -08006920TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006921 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006922 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006923 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006924 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006925 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6926 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6927 IdGenerator::getSource(repeatEvent->getId()));
6928 }
6929}
6930
6931TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006932 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006933 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006934
6935 std::unordered_set<int32_t> idSet;
6936 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006937 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006938 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6939 int32_t id = repeatEvent->getId();
6940 EXPECT_EQ(idSet.end(), idSet.find(id));
6941 idSet.insert(id);
6942 }
6943}
6944
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006945/* Test InputDispatcher for MultiDisplay */
6946class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6947public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006948 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006949 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006950
Chris Yea209fde2020-07-22 13:54:51 -07006951 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006952 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006953 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006954
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006955 // Set focus window for primary display, but focused display would be second one.
6956 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006957 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006958 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6959
Vishnu Nair958da932020-08-21 17:12:37 -07006960 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006961 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006962
Chris Yea209fde2020-07-22 13:54:51 -07006963 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006964 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006965 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006966 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006967 // Set focus display to second one.
6968 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6969 // Set focus window for second display.
6970 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006971 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006972 mDispatcher->onWindowInfosChanged(
6973 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006974 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006975 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006976 }
6977
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006978 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006979 InputDispatcherTest::TearDown();
6980
Chris Yea209fde2020-07-22 13:54:51 -07006981 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006982 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006983 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006984 windowInSecondary.clear();
6985 }
6986
6987protected:
Chris Yea209fde2020-07-22 13:54:51 -07006988 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006989 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006990 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006991 sp<FakeWindowHandle> windowInSecondary;
6992};
6993
6994TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6995 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006997 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006999 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007000 windowInSecondary->assertNoEvents();
7001
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007002 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007004 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007006 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007007 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007008}
7009
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007010TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007011 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007013 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007014 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007015 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007016 windowInSecondary->assertNoEvents();
7017
7018 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007020 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007021 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007022 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007023
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007024 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007025 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007026
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007027 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007028 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007029 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007030
7031 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007032 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007033 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007034 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007035 windowInSecondary->assertNoEvents();
7036}
7037
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007038// Test per-display input monitors for motion event.
7039TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007040 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007041 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007042 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007043 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007044
7045 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007047 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007048 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007049 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007050 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007051 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007052 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007053
7054 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007056 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007058 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007059 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007060 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007061 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007062
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007063 // Lift up the touch from the second display
7064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007065 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7067 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7068 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7069
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007070 // Test inject a non-pointer motion event.
7071 // If specific a display, it will dispatch to the focused window of particular display,
7072 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007074 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007076 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007077 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007078 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007079 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007080}
7081
7082// Test per-display input monitors for key event.
7083TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007084 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007085 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007086 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007087 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007088 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007089
7090 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007092 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007093 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007094 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007095 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007096 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007097}
7098
Vishnu Nair958da932020-08-21 17:12:37 -07007099TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7100 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007101 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007102 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007103 mDispatcher->onWindowInfosChanged(
7104 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7105 *windowInSecondary->getInfo()},
7106 {},
7107 0,
7108 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007109 setFocusedWindow(secondWindowInPrimary);
7110 windowInPrimary->consumeFocusEvent(false);
7111 secondWindowInPrimary->consumeFocusEvent(true);
7112
7113 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7115 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007116 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007117 windowInPrimary->assertNoEvents();
7118 windowInSecondary->assertNoEvents();
7119 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7120}
7121
Arthur Hungdfd528e2021-12-08 13:23:04 +00007122TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7123 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007124 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007125 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007126 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007127
7128 // Test touch down on primary display.
7129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007130 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7132 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7133 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7134
7135 // Test touch down on second display.
7136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007137 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007138 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7139 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7140 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7141
7142 // Trigger cancel touch.
7143 mDispatcher->cancelCurrentTouch();
7144 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7145 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7146 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7147 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7148
7149 // Test inject a move motion event, no window/monitor should receive the event.
7150 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007151 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007152 ADISPLAY_ID_DEFAULT, {110, 200}))
7153 << "Inject motion event should return InputEventInjectionResult::FAILED";
7154 windowInPrimary->assertNoEvents();
7155 monitorInPrimary.assertNoEvents();
7156
7157 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007158 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007159 SECOND_DISPLAY_ID, {110, 200}))
7160 << "Inject motion event should return InputEventInjectionResult::FAILED";
7161 windowInSecondary->assertNoEvents();
7162 monitorInSecondary.assertNoEvents();
7163}
7164
Jackal Guof9696682018-10-05 12:23:23 +08007165class InputFilterTest : public InputDispatcherTest {
7166protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007167 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7168 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007169 NotifyMotionArgs motionArgs;
7170
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007171 motionArgs =
7172 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007173 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007174 motionArgs =
7175 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007176 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007177 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007178 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007179 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007180 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007181 } else {
7182 mFakePolicy->assertFilterInputEventWasNotCalled();
7183 }
7184 }
7185
7186 void testNotifyKey(bool expectToBeFiltered) {
7187 NotifyKeyArgs keyArgs;
7188
7189 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007190 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007191 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007192 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007193 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007194
7195 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007196 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007197 } else {
7198 mFakePolicy->assertFilterInputEventWasNotCalled();
7199 }
7200 }
7201};
7202
7203// Test InputFilter for MotionEvent
7204TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7205 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007206 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7207 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007208
7209 // Enable InputFilter
7210 mDispatcher->setInputFilterEnabled(true);
7211 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007212 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7213 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007214
7215 // Disable InputFilter
7216 mDispatcher->setInputFilterEnabled(false);
7217 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007218 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7219 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007220}
7221
7222// Test InputFilter for KeyEvent
7223TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7224 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007225 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007226
7227 // Enable InputFilter
7228 mDispatcher->setInputFilterEnabled(true);
7229 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007230 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007231
7232 // Disable InputFilter
7233 mDispatcher->setInputFilterEnabled(false);
7234 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007235 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007236}
7237
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007238// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7239// logical display coordinate space.
7240TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7241 ui::Transform firstDisplayTransform;
7242 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7243 ui::Transform secondDisplayTransform;
7244 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7245
7246 std::vector<gui::DisplayInfo> displayInfos(2);
7247 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7248 displayInfos[0].transform = firstDisplayTransform;
7249 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7250 displayInfos[1].transform = secondDisplayTransform;
7251
Patrick Williamsd828f302023-04-28 17:52:08 -05007252 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007253
7254 // Enable InputFilter
7255 mDispatcher->setInputFilterEnabled(true);
7256
7257 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007258 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7259 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007260}
7261
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007262class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7263protected:
7264 virtual void SetUp() override {
7265 InputDispatcherTest::SetUp();
7266
7267 /**
7268 * We don't need to enable input filter to test the injected event policy, but we enabled it
7269 * here to make the tests more realistic, since this policy only matters when inputfilter is
7270 * on.
7271 */
7272 mDispatcher->setInputFilterEnabled(true);
7273
7274 std::shared_ptr<InputApplicationHandle> application =
7275 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007276 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7277 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007278
7279 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7280 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007281 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007282 setFocusedWindow(mWindow);
7283 mWindow->consumeFocusEvent(true);
7284 }
7285
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007286 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7287 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007288 KeyEvent event;
7289
7290 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7291 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7292 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007293 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007294 const int32_t additionalPolicyFlags =
7295 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007297 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007298 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007299 policyFlags | additionalPolicyFlags));
7300
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007301 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007302 }
7303
7304 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7305 int32_t flags) {
7306 MotionEvent event;
7307 PointerProperties pointerProperties[1];
7308 PointerCoords pointerCoords[1];
7309 pointerProperties[0].clear();
7310 pointerProperties[0].id = 0;
7311 pointerCoords[0].clear();
7312 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7313 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7314
7315 ui::Transform identityTransform;
7316 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7317 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7318 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7319 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7320 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007321 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007322 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007323 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007324
7325 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007327 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007328 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007329 policyFlags | additionalPolicyFlags));
7330
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007331 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007332 }
7333
7334private:
7335 sp<FakeWindowHandle> mWindow;
7336};
7337
7338TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007339 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7340 // filter. Without it, the event will no different from a regularly injected event, and the
7341 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007342 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7343 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007344}
7345
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007346TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007347 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007348 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007349 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7350}
7351
7352TEST_F(InputFilterInjectionPolicyTest,
7353 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7354 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007355 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007356 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007357}
7358
7359TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007360 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7361 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007362}
7363
chaviwfd6d3512019-03-25 13:23:49 -07007364class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007365 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007366 InputDispatcherTest::SetUp();
7367
Chris Yea209fde2020-07-22 13:54:51 -07007368 std::shared_ptr<FakeApplicationHandle> application =
7369 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007370 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007371 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007372 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007373
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007374 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007375 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007376 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007377
7378 // Set focused application.
7379 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007380 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007381
7382 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007383 mDispatcher->onWindowInfosChanged(
7384 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007385 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007386 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007387 }
7388
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007389 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007390 InputDispatcherTest::TearDown();
7391
7392 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007393 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007394 }
7395
7396protected:
7397 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007398 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007399 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007400};
7401
7402// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7403// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7404// the onPointerDownOutsideFocus callback.
7405TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007407 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007408 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007409 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007410 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007411
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007412 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007413 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7414}
7415
7416// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7417// DOWN on the window that doesn't have focus. Ensure no window received the
7418// onPointerDownOutsideFocus callback.
7419TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007421 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7422 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007424 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007425
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007426 ASSERT_TRUE(mDispatcher->waitForIdle());
7427 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007428}
7429
7430// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7431// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7432TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007434 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007435 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007436 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007437
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007438 ASSERT_TRUE(mDispatcher->waitForIdle());
7439 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007440}
7441
7442// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7443// DOWN on the window that already has focus. Ensure no window received the
7444// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007445TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007447 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007448 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007450 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007451
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007452 ASSERT_TRUE(mDispatcher->waitForIdle());
7453 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007454}
7455
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007456// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7457// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7458TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7459 const MotionEvent event =
7460 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7461 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007462 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007463 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7464 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7467 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7468
7469 ASSERT_TRUE(mDispatcher->waitForIdle());
7470 mFakePolicy->assertOnPointerDownWasNotCalled();
7471 // Ensure that the unfocused window did not receive any FOCUS events.
7472 mUnfocusedWindow->assertNoEvents();
7473}
7474
chaviwaf87b3e2019-10-01 16:59:28 -07007475// These tests ensures we can send touch events to a single client when there are multiple input
7476// windows that point to the same client token.
7477class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7478 virtual void SetUp() override {
7479 InputDispatcherTest::SetUp();
7480
Chris Yea209fde2020-07-22 13:54:51 -07007481 std::shared_ptr<FakeApplicationHandle> application =
7482 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007483 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7484 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007485 mWindow1->setFrame(Rect(0, 0, 100, 100));
7486
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007487 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7488 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007489 mWindow2->setFrame(Rect(100, 100, 200, 200));
7490
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007491 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007492 }
7493
7494protected:
7495 sp<FakeWindowHandle> mWindow1;
7496 sp<FakeWindowHandle> mWindow2;
7497
7498 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007499 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007500 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7501 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007502 }
7503
7504 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7505 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007506 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007507 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007508
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007509 ASSERT_NE(nullptr, motionEvent)
7510 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007511
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007512 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007513 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007514
7515 for (size_t i = 0; i < points.size(); i++) {
7516 float expectedX = points[i].x;
7517 float expectedY = points[i].y;
7518
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007519 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007520 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007521 << ", got " << motionEvent->getX(i);
7522 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007523 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007524 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007525 }
7526 }
chaviw9eaa22c2020-07-01 16:21:27 -07007527
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007528 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007529 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007530 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7531 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007532
7533 // Always consume from window1 since it's the window that has the InputReceiver
7534 consumeMotionEvent(mWindow1, action, expectedPoints);
7535 }
chaviwaf87b3e2019-10-01 16:59:28 -07007536};
7537
7538TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7539 // Touch Window 1
7540 PointF touchedPoint = {10, 10};
7541 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007542 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007543
7544 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007545 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007546
7547 // Touch Window 2
7548 touchedPoint = {150, 150};
7549 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007550 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007551}
7552
chaviw9eaa22c2020-07-01 16:21:27 -07007553TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7554 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007555 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007556 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007557
7558 // Touch Window 1
7559 PointF touchedPoint = {10, 10};
7560 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007561 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007562 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007563 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007564
7565 // Touch Window 2
7566 touchedPoint = {150, 150};
7567 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007568 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7569 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007570
chaviw9eaa22c2020-07-01 16:21:27 -07007571 // Update the transform so rotation is set
7572 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007573 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007574 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7575 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007576}
7577
chaviw9eaa22c2020-07-01 16:21:27 -07007578TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007579 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007580 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007581
7582 // Touch Window 1
7583 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7584 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007585 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007586
7587 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007588 touchedPoints.push_back(PointF{150, 150});
7589 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007590 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007591
chaviw9eaa22c2020-07-01 16:21:27 -07007592 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007593 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007594 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007595
chaviw9eaa22c2020-07-01 16:21:27 -07007596 // Update the transform so rotation is set for Window 2
7597 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007598 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007599 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007600 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007601}
7602
chaviw9eaa22c2020-07-01 16:21:27 -07007603TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007604 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007605 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007606
7607 // Touch Window 1
7608 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7609 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007610 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007611
7612 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007613 touchedPoints.push_back(PointF{150, 150});
7614 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007615
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007616 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007617
7618 // Move both windows
7619 touchedPoints = {{20, 20}, {175, 175}};
7620 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7621 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7622
chaviw9eaa22c2020-07-01 16:21:27 -07007623 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007624
chaviw9eaa22c2020-07-01 16:21:27 -07007625 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007626 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007627 expectedPoints.pop_back();
7628
7629 // Touch Window 2
7630 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007631 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007632 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007633 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007634
7635 // Move both windows
7636 touchedPoints = {{20, 20}, {175, 175}};
7637 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7638 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7639
7640 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007641}
7642
7643TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7644 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007645 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007646
7647 // Touch Window 1
7648 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7649 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007650 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007651
7652 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007653 touchedPoints.push_back(PointF{150, 150});
7654 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007655
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007656 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007657
7658 // Move both windows
7659 touchedPoints = {{20, 20}, {175, 175}};
7660 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7661 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7662
chaviw9eaa22c2020-07-01 16:21:27 -07007663 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007664}
7665
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007666/**
7667 * When one of the windows is slippery, the touch should not slip into the other window with the
7668 * same input channel.
7669 */
7670TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7671 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007672 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007673
7674 // Touch down in window 1
7675 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7676 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7677 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7678
7679 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7680 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7681 // getting generated.
7682 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7683 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7684
7685 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7686}
7687
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007688/**
7689 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7690 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7691 * that the pointer is hovering over may have a different transform.
7692 */
7693TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007694 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007695
7696 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007697 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7698 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7699 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007700 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7701 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007702 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7704 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7705 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007706 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7707 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7708 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7709}
7710
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007711class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7712 virtual void SetUp() override {
7713 InputDispatcherTest::SetUp();
7714
Chris Yea209fde2020-07-22 13:54:51 -07007715 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007716 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007717 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7718 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007719 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007720 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007721 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007722
7723 // Set focused application.
7724 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7725
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007726 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007727 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007728 mWindow->consumeFocusEvent(true);
7729 }
7730
7731 virtual void TearDown() override {
7732 InputDispatcherTest::TearDown();
7733 mWindow.clear();
7734 }
7735
7736protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007737 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007738 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007739 sp<FakeWindowHandle> mWindow;
7740 static constexpr PointF WINDOW_LOCATION = {20, 20};
7741
7742 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007745 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007747 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007748 WINDOW_LOCATION));
7749 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007750
7751 sp<FakeWindowHandle> addSpyWindow() {
7752 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007753 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007754 spy->setTrustedOverlay(true);
7755 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007756 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007757 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007758 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007759 return spy;
7760 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007761};
7762
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007763// Send a tap and respond, which should not cause an ANR.
7764TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7765 tapOnWindow();
7766 mWindow->consumeMotionDown();
7767 mWindow->consumeMotionUp();
7768 ASSERT_TRUE(mDispatcher->waitForIdle());
7769 mFakePolicy->assertNotifyAnrWasNotCalled();
7770}
7771
7772// Send a regular key and respond, which should not cause an ANR.
7773TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007775 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7776 ASSERT_TRUE(mDispatcher->waitForIdle());
7777 mFakePolicy->assertNotifyAnrWasNotCalled();
7778}
7779
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007780TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7781 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007782 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007783 mWindow->consumeFocusEvent(false);
7784
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007785 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007786 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7787 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007788 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007790 // Key will not go to window because we have no focused window.
7791 // The 'no focused window' ANR timer should start instead.
7792
7793 // Now, the focused application goes away.
7794 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7795 // The key should get dropped and there should be no ANR.
7796
7797 ASSERT_TRUE(mDispatcher->waitForIdle());
7798 mFakePolicy->assertNotifyAnrWasNotCalled();
7799}
7800
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007801// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007802// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7803// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007804TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007806 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007807 WINDOW_LOCATION));
7808
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007809 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7810 ASSERT_TRUE(sequenceNum);
7811 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007812 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007813
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007814 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007815 mWindow->consumeMotionEvent(
7816 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007817 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007818 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007819}
7820
7821// Send a key to the app and have the app not respond right away.
7822TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7823 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007825 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7826 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007827 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007828 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007829 ASSERT_TRUE(mDispatcher->waitForIdle());
7830}
7831
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007832// We have a focused application, but no focused window
7833TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007834 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007835 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007836 mWindow->consumeFocusEvent(false);
7837
7838 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007840 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007841 WINDOW_LOCATION));
7842 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7843 mDispatcher->waitForIdle();
7844 mFakePolicy->assertNotifyAnrWasNotCalled();
7845
7846 // Once a focused event arrives, we get an ANR for this application
7847 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7848 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007849 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007850 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007851 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007852 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007853 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007854 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007855 ASSERT_TRUE(mDispatcher->waitForIdle());
7856}
7857
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007858/**
7859 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7860 * there will not be an ANR.
7861 */
7862TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7863 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007864 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007865 mWindow->consumeFocusEvent(false);
7866
7867 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007868 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7869 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007870 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7871 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7872
7873 // Define a valid key down event that is stale (too old).
7874 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007875 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007876 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007877
7878 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7879
7880 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007881 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007882 InputEventInjectionSync::WAIT_FOR_RESULT,
7883 INJECT_EVENT_TIMEOUT, policyFlags);
7884 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7885 << "Injection should fail because the event is stale";
7886
7887 ASSERT_TRUE(mDispatcher->waitForIdle());
7888 mFakePolicy->assertNotifyAnrWasNotCalled();
7889 mWindow->assertNoEvents();
7890}
7891
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007892// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007893// Make sure that we don't notify policy twice about the same ANR.
7894TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007895 const std::chrono::duration appTimeout = 400ms;
7896 mApplication->setDispatchingTimeout(appTimeout);
7897 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7898
Vishnu Nair47074b82020-08-14 11:54:47 -07007899 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007900 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007901 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007902
7903 // Once a focused event arrives, we get an ANR for this application
7904 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7905 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007906 const std::chrono::duration eventInjectionTimeout = 100ms;
7907 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007908 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007909 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007910 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7911 /*allowKeyRepeat=*/false);
7912 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7913 << "result=" << ftl::enum_string(result);
7914 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7915 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7916 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7917 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007918
Vishnu Naire4df8752022-09-08 09:17:55 -07007919 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007920 // ANR should not be raised again. It is up to policy to do that if it desires.
7921 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007923 // If we now get a focused window, the ANR should stop, but the policy handles that via
7924 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007925 ASSERT_TRUE(mDispatcher->waitForIdle());
7926}
7927
7928// We have a focused application, but no focused window
7929TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007930 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007931 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007932 mWindow->consumeFocusEvent(false);
7933
7934 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007935 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936
Vishnu Naire4df8752022-09-08 09:17:55 -07007937 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7938 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007939
7940 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007941 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942 ASSERT_TRUE(mDispatcher->waitForIdle());
7943 mWindow->assertNoEvents();
7944}
7945
7946/**
7947 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7948 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7949 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7950 * the ANR mechanism should still work.
7951 *
7952 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7953 * DOWN event, while not responding on the second one.
7954 */
7955TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7956 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007957 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007958 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7959 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7960 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007961 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007962
7963 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007964 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007965 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7966 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7967 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007968 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007969
7970 // We have now sent down and up. Let's consume first event and then ANR on the second.
7971 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7972 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007973 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007974}
7975
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007976// A spy window can receive an ANR
7977TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7978 sp<FakeWindowHandle> spy = addSpyWindow();
7979
7980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007981 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007982 WINDOW_LOCATION));
7983 mWindow->consumeMotionDown();
7984
7985 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7986 ASSERT_TRUE(sequenceNum);
7987 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007988 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007989
7990 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007991 spy->consumeMotionEvent(
7992 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007993 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007994 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007995}
7996
7997// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007998// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007999TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8000 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008001
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008003 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008004 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008006
8007 // Stuck on the ACTION_UP
8008 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008009 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008010
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008011 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008012 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008013 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8014 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008015
8016 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8017 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008018 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008019 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008020 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021}
8022
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008023// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008024// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008025TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8026 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008027
8028 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008029 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8030 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008031
8032 mWindow->consumeMotionDown();
8033 // Stuck on the ACTION_UP
8034 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008035 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008036
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008037 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008038 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008039 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8040 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008041
8042 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8043 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008044 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008045 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008046 spy->assertNoEvents();
8047}
8048
8049TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008050 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008051
Prabir Pradhanfb549072023-10-05 19:17:36 +00008052 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008053
8054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008056 WINDOW_LOCATION));
8057
8058 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8059 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8060 ASSERT_TRUE(consumeSeq);
8061
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008062 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8063 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008064
8065 monitor.finishEvent(*consumeSeq);
8066 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8067
8068 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008069 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008070}
8071
8072// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8073// process events, you don't get an anr. When the window later becomes unresponsive again, you
8074// get an ANR again.
8075// 1. tap -> block on ACTION_UP -> receive ANR
8076// 2. consume all pending events (= queue becomes healthy again)
8077// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8078TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8079 tapOnWindow();
8080
8081 mWindow->consumeMotionDown();
8082 // Block on ACTION_UP
8083 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008084 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008085 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8086 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008087 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008088 mWindow->assertNoEvents();
8089
8090 tapOnWindow();
8091 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008092 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008093 mWindow->consumeMotionUp();
8094
8095 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008096 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008097 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008098 mWindow->assertNoEvents();
8099}
8100
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008101// If a connection remains unresponsive for a while, make sure policy is only notified once about
8102// it.
8103TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008105 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008106 WINDOW_LOCATION));
8107
8108 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008109 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008110 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008111 // 'notifyConnectionUnresponsive' should only be called once per connection
8112 mFakePolicy->assertNotifyAnrWasNotCalled();
8113 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008114 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008115 mWindow->consumeMotionEvent(
8116 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008117 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008118 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008119 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008120 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008121}
8122
8123/**
8124 * 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 -07008125 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008126 *
8127 * Warning!!!
8128 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8129 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008130 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8132 *
8133 * If that value changes, this test should also change.
8134 */
8135TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8136 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008137 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008138
8139 tapOnWindow();
8140 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8141 ASSERT_TRUE(downSequenceNum);
8142 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8143 ASSERT_TRUE(upSequenceNum);
8144 // Don't finish the events yet, and send a key
8145 // Injection will "succeed" because we will eventually give up and send the key to the focused
8146 // window even if motions are still being processed. But because the injection timeout is short,
8147 // we will receive INJECTION_TIMED_OUT as the result.
8148
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008149 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008150 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8151 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008152 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008153 // Key will not be sent to the window, yet, because the window is still processing events
8154 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008155 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8156 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8157 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8158 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008159
8160 std::this_thread::sleep_for(500ms);
8161 // if we wait long enough though, dispatcher will give up, and still send the key
8162 // to the focused window, even though we have not yet finished the motion event
8163 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8164 mWindow->finishEvent(*downSequenceNum);
8165 mWindow->finishEvent(*upSequenceNum);
8166}
8167
8168/**
8169 * If a window is processing a motion event, and then a key event comes in, the key event should
8170 * not go to the focused window until the motion is processed.
8171 * If then a new motion comes in, then the pending key event should be going to the currently
8172 * focused window right away.
8173 */
8174TEST_F(InputDispatcherSingleWindowAnr,
8175 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8176 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008177 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008178
8179 tapOnWindow();
8180 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8181 ASSERT_TRUE(downSequenceNum);
8182 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8183 ASSERT_TRUE(upSequenceNum);
8184 // Don't finish the events yet, and send a key
8185 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008187 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8188 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008189 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008190 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8191 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8192 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8193 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194
8195 // Now tap down again. It should cause the pending key to go to the focused window right away.
8196 tapOnWindow();
8197 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
8198 // the other events yet. We can finish events in any order.
8199 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8200 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
8201 mWindow->consumeMotionDown();
8202 mWindow->consumeMotionUp();
8203 mWindow->assertNoEvents();
8204}
8205
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008206/**
8207 * Send an event to the app and have the app not respond right away.
8208 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8209 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8210 * At some point, the window becomes responsive again.
8211 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8212 */
8213TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8215 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8216 .build());
8217
8218 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8219 ASSERT_TRUE(sequenceNum);
8220 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8221 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8222
8223 mWindow->finishEvent(*sequenceNum);
8224 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8225 ASSERT_TRUE(mDispatcher->waitForIdle());
8226 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8227
8228 // Now that the window is responsive, let's continue the gesture.
8229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8230 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8231 .build());
8232
8233 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8234 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8235 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8236 .build());
8237
8238 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8239 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8240 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8241 .build());
8242 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8243 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8244 .build());
8245 // We already canceled this pointer, so the window shouldn't get any new events.
8246 mWindow->assertNoEvents();
8247
8248 // Start another one.
8249 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8250 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8251 .build());
8252 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8253}
8254
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008255class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8256 virtual void SetUp() override {
8257 InputDispatcherTest::SetUp();
8258
Chris Yea209fde2020-07-22 13:54:51 -07008259 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008260 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008261 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8262 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008263 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008264 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008265 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008266
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008267 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8268 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008269 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008270 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008271
8272 // Set focused application.
8273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008274 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008275
8276 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008277 mDispatcher->onWindowInfosChanged(
8278 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008279 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280 mFocusedWindow->consumeFocusEvent(true);
8281 }
8282
8283 virtual void TearDown() override {
8284 InputDispatcherTest::TearDown();
8285
8286 mUnfocusedWindow.clear();
8287 mFocusedWindow.clear();
8288 }
8289
8290protected:
Chris Yea209fde2020-07-22 13:54:51 -07008291 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008292 sp<FakeWindowHandle> mUnfocusedWindow;
8293 sp<FakeWindowHandle> mFocusedWindow;
8294 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8295 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8296 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8297
8298 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8299
8300 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8301
8302private:
8303 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008305 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008306 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008308 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008309 location));
8310 }
8311};
8312
8313// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8314// should be ANR'd first.
8315TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008317 injectMotionEvent(*mDispatcher,
8318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8319 AINPUT_SOURCE_TOUCHSCREEN)
8320 .pointer(PointerBuilder(0, ToolType::FINGER)
8321 .x(FOCUSED_WINDOW_LOCATION.x)
8322 .y(FOCUSED_WINDOW_LOCATION.y))
8323 .build()));
8324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8325 injectMotionEvent(*mDispatcher,
8326 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8327 AINPUT_SOURCE_TOUCHSCREEN)
8328 .pointer(PointerBuilder(0, ToolType::FINGER)
8329 .x(FOCUSED_WINDOW_LOCATION.x)
8330 .y(FOCUSED_WINDOW_LOCATION.y))
8331 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008332 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008333 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008334 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008335 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008336 // We consumed all events, so no ANR
8337 ASSERT_TRUE(mDispatcher->waitForIdle());
8338 mFakePolicy->assertNotifyAnrWasNotCalled();
8339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008341 injectMotionEvent(*mDispatcher,
8342 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8343 AINPUT_SOURCE_TOUCHSCREEN)
8344 .pointer(PointerBuilder(0, ToolType::FINGER)
8345 .x(FOCUSED_WINDOW_LOCATION.x)
8346 .y(FOCUSED_WINDOW_LOCATION.y))
8347 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008348 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8349 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008350
8351 const std::chrono::duration timeout =
8352 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008353 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008354
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008355 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008356 mFocusedWindow->consumeMotionDown();
8357 // This cancel is generated because the connection was unresponsive
8358 mFocusedWindow->consumeMotionCancel();
8359 mFocusedWindow->assertNoEvents();
8360 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008361 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008362 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8363 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008364 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008365}
8366
8367// If we have 2 windows with identical timeouts that are both unresponsive,
8368// it doesn't matter which order they should have ANR.
8369// But we should receive ANR for both.
8370TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8371 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008372 mUnfocusedWindow->setDispatchingTimeout(
8373 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008374 mDispatcher->onWindowInfosChanged(
8375 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008376
8377 tapOnFocusedWindow();
8378 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008379 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008380 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8381 mFocusedWindow->getDispatchingTimeout(
8382 DISPATCHING_TIMEOUT)),
8383 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8384
8385 ASSERT_THAT(anrConnectionTokens,
8386 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8387 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008388
8389 ASSERT_TRUE(mDispatcher->waitForIdle());
8390 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008391
8392 mFocusedWindow->consumeMotionDown();
8393 mFocusedWindow->consumeMotionUp();
8394 mUnfocusedWindow->consumeMotionOutside();
8395
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008396 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8397 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008398
8399 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008400 ASSERT_THAT(responsiveTokens,
8401 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8402 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008403 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008404}
8405
8406// If a window is already not responding, the second tap on the same window should be ignored.
8407// We should also log an error to account for the dropped event (not tested here).
8408// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8409TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8410 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008411 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008412 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008413 // Receive the events, but don't respond
8414 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8415 ASSERT_TRUE(downEventSequenceNum);
8416 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8417 ASSERT_TRUE(upEventSequenceNum);
8418 const std::chrono::duration timeout =
8419 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008420 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008421
8422 // Tap once again
8423 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008424 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008426 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008427 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008428 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008429 FOCUSED_WINDOW_LOCATION));
8430 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8431 // valid touch target
8432 mUnfocusedWindow->assertNoEvents();
8433
8434 // Consume the first tap
8435 mFocusedWindow->finishEvent(*downEventSequenceNum);
8436 mFocusedWindow->finishEvent(*upEventSequenceNum);
8437 ASSERT_TRUE(mDispatcher->waitForIdle());
8438 // The second tap did not go to the focused window
8439 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008440 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008441 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8442 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008443 mFakePolicy->assertNotifyAnrWasNotCalled();
8444}
8445
8446// If you tap outside of all windows, there will not be ANR
8447TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008448 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008449 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008450 LOCATION_OUTSIDE_ALL_WINDOWS));
8451 ASSERT_TRUE(mDispatcher->waitForIdle());
8452 mFakePolicy->assertNotifyAnrWasNotCalled();
8453}
8454
8455// Since the focused window is paused, tapping on it should not produce any events
8456TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8457 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008458 mDispatcher->onWindowInfosChanged(
8459 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008461 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008462 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008463 FOCUSED_WINDOW_LOCATION));
8464
8465 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8466 ASSERT_TRUE(mDispatcher->waitForIdle());
8467 // Should not ANR because the window is paused, and touches shouldn't go to it
8468 mFakePolicy->assertNotifyAnrWasNotCalled();
8469
8470 mFocusedWindow->assertNoEvents();
8471 mUnfocusedWindow->assertNoEvents();
8472}
8473
8474/**
8475 * 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 -07008476 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008477 * If a different window becomes focused at this time, the key should go to that window instead.
8478 *
8479 * Warning!!!
8480 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8481 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008482 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008483 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8484 *
8485 * If that value changes, this test should also change.
8486 */
8487TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8488 // Set a long ANR timeout to prevent it from triggering
8489 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008490 mDispatcher->onWindowInfosChanged(
8491 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008492
8493 tapOnUnfocusedWindow();
8494 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8495 ASSERT_TRUE(downSequenceNum);
8496 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8497 ASSERT_TRUE(upSequenceNum);
8498 // Don't finish the events yet, and send a key
8499 // Injection will succeed because we will eventually give up and send the key to the focused
8500 // window even if motions are still being processed.
8501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008502 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008503 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8504 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008506 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008507 // and the key remains pending, waiting for the touch events to be processed.
8508 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8509 // under the hood.
8510 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8511 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008512
8513 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008514 mFocusedWindow->setFocusable(false);
8515 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008516 mDispatcher->onWindowInfosChanged(
8517 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008518 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008519
8520 // Focus events should precede the key events
8521 mUnfocusedWindow->consumeFocusEvent(true);
8522 mFocusedWindow->consumeFocusEvent(false);
8523
8524 // Finish the tap events, which should unblock dispatcher
8525 mUnfocusedWindow->finishEvent(*downSequenceNum);
8526 mUnfocusedWindow->finishEvent(*upSequenceNum);
8527
8528 // Now that all queues are cleared and no backlog in the connections, the key event
8529 // can finally go to the newly focused "mUnfocusedWindow".
8530 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8531 mFocusedWindow->assertNoEvents();
8532 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008533 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008534}
8535
8536// When the touch stream is split across 2 windows, and one of them does not respond,
8537// then ANR should be raised and the touch should be canceled for the unresponsive window.
8538// The other window should not be affected by that.
8539TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8540 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008541 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8542 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8543 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008544 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008545 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008546
8547 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008548 mDispatcher->notifyMotion(
8549 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8550 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008551
8552 const std::chrono::duration timeout =
8553 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008554 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008555
8556 mUnfocusedWindow->consumeMotionDown();
8557 mFocusedWindow->consumeMotionDown();
8558 // Focused window may or may not receive ACTION_MOVE
8559 // But it should definitely receive ACTION_CANCEL due to the ANR
8560 InputEvent* event;
8561 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8562 ASSERT_TRUE(moveOrCancelSequenceNum);
8563 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8564 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008565 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008566 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8567 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8568 mFocusedWindow->consumeMotionCancel();
8569 } else {
8570 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8571 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008572 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008573 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8574 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008575
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008576 mUnfocusedWindow->assertNoEvents();
8577 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008578 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008579}
8580
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008581/**
8582 * If we have no focused window, and a key comes in, we start the ANR timer.
8583 * The focused application should add a focused window before the timer runs out to prevent ANR.
8584 *
8585 * If the user touches another application during this time, the key should be dropped.
8586 * Next, if a new focused window comes in, without toggling the focused application,
8587 * then no ANR should occur.
8588 *
8589 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8590 * but in some cases the policy may not update the focused application.
8591 */
8592TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8593 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8594 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008595 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008596 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8597 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8598 mFocusedWindow->setFocusable(false);
8599
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008600 mDispatcher->onWindowInfosChanged(
8601 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008602 mFocusedWindow->consumeFocusEvent(false);
8603
8604 // Send a key. The ANR timer should start because there is no focused window.
8605 // 'focusedApplication' will get blamed if this timer completes.
8606 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008607 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008608 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8609 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008610 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008612
8613 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8614 // then the injected touches won't cause the focused event to get dropped.
8615 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8616 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8617 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8618 // For this test, it means that the key would get delivered to the window once it becomes
8619 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008620 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008621
8622 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008623 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8624 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8625 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008626
8627 // We do not consume the motion right away, because that would require dispatcher to first
8628 // process (== drop) the key event, and by that time, ANR will be raised.
8629 // Set the focused window first.
8630 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008631 mDispatcher->onWindowInfosChanged(
8632 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008633 setFocusedWindow(mFocusedWindow);
8634 mFocusedWindow->consumeFocusEvent(true);
8635 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8636 // to another application. This could be a bug / behaviour in the policy.
8637
8638 mUnfocusedWindow->consumeMotionDown();
8639
8640 ASSERT_TRUE(mDispatcher->waitForIdle());
8641 // Should not ANR because we actually have a focused window. It was just added too slowly.
8642 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8643}
8644
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008645// These tests ensure we cannot send touch events to a window that's positioned behind a window
8646// that has feature NO_INPUT_CHANNEL.
8647// Layout:
8648// Top (closest to user)
8649// mNoInputWindow (above all windows)
8650// mBottomWindow
8651// Bottom (furthest from user)
8652class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8653 virtual void SetUp() override {
8654 InputDispatcherTest::SetUp();
8655
8656 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008657 mNoInputWindow =
8658 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8659 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008660 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008661 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008662 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8663 // It's perfectly valid for this window to not have an associated input channel
8664
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008665 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8666 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008667 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8668
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008669 mDispatcher->onWindowInfosChanged(
8670 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008671 }
8672
8673protected:
8674 std::shared_ptr<FakeApplicationHandle> mApplication;
8675 sp<FakeWindowHandle> mNoInputWindow;
8676 sp<FakeWindowHandle> mBottomWindow;
8677};
8678
8679TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8680 PointF touchedPoint = {10, 10};
8681
Prabir Pradhan678438e2023-04-13 19:32:51 +00008682 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8683 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8684 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008685
8686 mNoInputWindow->assertNoEvents();
8687 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8688 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8689 // and therefore should prevent mBottomWindow from receiving touches
8690 mBottomWindow->assertNoEvents();
8691}
8692
8693/**
8694 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8695 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8696 */
8697TEST_F(InputDispatcherMultiWindowOcclusionTests,
8698 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008699 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8700 "Window with input channel and NO_INPUT_CHANNEL",
8701 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008702
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008703 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008704 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008705 mDispatcher->onWindowInfosChanged(
8706 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008707
8708 PointF touchedPoint = {10, 10};
8709
Prabir Pradhan678438e2023-04-13 19:32:51 +00008710 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8711 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8712 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008713
8714 mNoInputWindow->assertNoEvents();
8715 mBottomWindow->assertNoEvents();
8716}
8717
Vishnu Nair958da932020-08-21 17:12:37 -07008718class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8719protected:
8720 std::shared_ptr<FakeApplicationHandle> mApp;
8721 sp<FakeWindowHandle> mWindow;
8722 sp<FakeWindowHandle> mMirror;
8723
8724 virtual void SetUp() override {
8725 InputDispatcherTest::SetUp();
8726 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008727 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8728 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8729 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008730 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8731 mWindow->setFocusable(true);
8732 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008733 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008734 }
8735};
8736
8737TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8738 // Request focus on a mirrored window
8739 setFocusedWindow(mMirror);
8740
8741 // window gets focused
8742 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008744 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008745 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8746}
8747
8748// A focused & mirrored window remains focused only if the window and its mirror are both
8749// focusable.
8750TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8751 setFocusedWindow(mMirror);
8752
8753 // window gets focused
8754 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008757 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008759 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008760 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8761
8762 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008763 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008764
8765 // window loses focus since one of the windows associated with the token in not focusable
8766 mWindow->consumeFocusEvent(false);
8767
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008768 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008769 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008770 mWindow->assertNoEvents();
8771}
8772
8773// A focused & mirrored window remains focused until the window and its mirror both become
8774// invisible.
8775TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8776 setFocusedWindow(mMirror);
8777
8778 // window gets focused
8779 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008781 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008782 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008784 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008785 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8786
8787 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008788 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008789
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008792 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008794 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008795 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8796
8797 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008798 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008799
8800 // window loses focus only after all windows associated with the token become invisible.
8801 mWindow->consumeFocusEvent(false);
8802
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008803 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008804 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008805 mWindow->assertNoEvents();
8806}
8807
8808// A focused & mirrored window remains focused until both windows are removed.
8809TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8810 setFocusedWindow(mMirror);
8811
8812 // window gets focused
8813 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008815 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008816 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008818 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008819 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8820
8821 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008822 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008823
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008825 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008826 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008828 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008829 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8830
8831 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008832 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008833 mWindow->consumeFocusEvent(false);
8834
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008836 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008837 mWindow->assertNoEvents();
8838}
8839
8840// Focus request can be pending until one window becomes visible.
8841TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8842 // Request focus on an invisible mirror.
8843 mWindow->setVisible(false);
8844 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008845 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008846 setFocusedWindow(mMirror);
8847
8848 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008850 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8851 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008852
8853 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008854 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008855
8856 // window gets focused
8857 mWindow->consumeFocusEvent(true);
8858 // window gets the pending key event
8859 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8860}
Prabir Pradhan99987712020-11-10 18:43:05 -08008861
8862class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8863protected:
8864 std::shared_ptr<FakeApplicationHandle> mApp;
8865 sp<FakeWindowHandle> mWindow;
8866 sp<FakeWindowHandle> mSecondWindow;
8867
8868 void SetUp() override {
8869 InputDispatcherTest::SetUp();
8870 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008871 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008872 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008873 mSecondWindow =
8874 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008875 mSecondWindow->setFocusable(true);
8876
8877 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008878 mDispatcher->onWindowInfosChanged(
8879 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008880
8881 setFocusedWindow(mWindow);
8882 mWindow->consumeFocusEvent(true);
8883 }
8884
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008885 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008886 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008887 }
8888
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008889 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8890 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008891 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008892 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8893 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008894 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008895 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008896 }
8897};
8898
8899TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8900 // Ensure that capture cannot be obtained for unfocused windows.
8901 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8902 mFakePolicy->assertSetPointerCaptureNotCalled();
8903 mSecondWindow->assertNoEvents();
8904
8905 // Ensure that capture can be enabled from the focus window.
8906 requestAndVerifyPointerCapture(mWindow, true);
8907
8908 // Ensure that capture cannot be disabled from a window that does not have capture.
8909 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8910 mFakePolicy->assertSetPointerCaptureNotCalled();
8911
8912 // Ensure that capture can be disabled from the window with capture.
8913 requestAndVerifyPointerCapture(mWindow, false);
8914}
8915
8916TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008917 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008918
8919 setFocusedWindow(mSecondWindow);
8920
8921 // Ensure that the capture disabled event was sent first.
8922 mWindow->consumeCaptureEvent(false);
8923 mWindow->consumeFocusEvent(false);
8924 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008925 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008926
8927 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008928 notifyPointerCaptureChanged({});
8929 notifyPointerCaptureChanged(request);
8930 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008931 mWindow->assertNoEvents();
8932 mSecondWindow->assertNoEvents();
8933 mFakePolicy->assertSetPointerCaptureNotCalled();
8934}
8935
8936TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008937 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008938
8939 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008940 notifyPointerCaptureChanged({});
8941 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008942
8943 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008944 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008945 mWindow->consumeCaptureEvent(false);
8946 mWindow->assertNoEvents();
8947}
8948
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008949TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8950 requestAndVerifyPointerCapture(mWindow, true);
8951
8952 // The first window loses focus.
8953 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008954 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008955 mWindow->consumeCaptureEvent(false);
8956
8957 // Request Pointer Capture from the second window before the notification from InputReader
8958 // arrives.
8959 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008960 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008961
8962 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008963 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008964
8965 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008966 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008967
8968 mSecondWindow->consumeFocusEvent(true);
8969 mSecondWindow->consumeCaptureEvent(true);
8970}
8971
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008972TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8973 // App repeatedly enables and disables capture.
8974 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8975 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8976 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8977 mFakePolicy->assertSetPointerCaptureCalled(false);
8978 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8979 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8980
8981 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8982 // first request is now stale, this should do nothing.
8983 notifyPointerCaptureChanged(firstRequest);
8984 mWindow->assertNoEvents();
8985
8986 // InputReader notifies that the second request was enabled.
8987 notifyPointerCaptureChanged(secondRequest);
8988 mWindow->consumeCaptureEvent(true);
8989}
8990
Prabir Pradhan7092e262022-05-03 16:51:09 +00008991TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8992 requestAndVerifyPointerCapture(mWindow, true);
8993
8994 // App toggles pointer capture off and on.
8995 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8996 mFakePolicy->assertSetPointerCaptureCalled(false);
8997
8998 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8999 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9000
9001 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9002 // preceding "disable" request.
9003 notifyPointerCaptureChanged(enableRequest);
9004
9005 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9006 // any notifications.
9007 mWindow->assertNoEvents();
9008}
9009
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009010/**
9011 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9012 * mouse movements don't affect the previous mouse hovering state.
9013 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9014 * HOVER_MOVE events).
9015 */
9016TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9017 // Mouse hover on the window
9018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9019 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9020 .build());
9021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9022 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9023 .build());
9024
9025 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9026 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9027
9028 // Start pointer capture
9029 requestAndVerifyPointerCapture(mWindow, true);
9030
9031 // Send some relative mouse movements and receive them in the window.
9032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9034 .build());
9035 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9036 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9037
9038 // Stop pointer capture
9039 requestAndVerifyPointerCapture(mWindow, false);
9040
9041 // Continue hovering on the window
9042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9044 .build());
9045 mWindow->consumeMotionEvent(
9046 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9047
9048 mWindow->assertNoEvents();
9049}
9050
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009051class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9052protected:
9053 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009054
9055 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9056 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9057
9058 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9059 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9060
9061 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9062 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9063 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9064 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9065 MAXIMUM_OBSCURING_OPACITY);
9066
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009067 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9068 static constexpr gui::Uid APP_B_UID{10002};
9069 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009070
9071 sp<FakeWindowHandle> mTouchWindow;
9072
9073 virtual void SetUp() override {
9074 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009075 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009076 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9077 }
9078
9079 virtual void TearDown() override {
9080 InputDispatcherTest::TearDown();
9081 mTouchWindow.clear();
9082 }
9083
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009084 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009085 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009086 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009087 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009088 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009089 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009090 return window;
9091 }
9092
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009093 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009094 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9095 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009096 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009097 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009098 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009099 return window;
9100 }
9101
9102 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009103 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9104 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9105 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009106 }
9107};
9108
9109TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009110 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009111 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009112 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009113
9114 touch();
9115
9116 mTouchWindow->assertNoEvents();
9117}
9118
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009119TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009120 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9121 const sp<FakeWindowHandle>& w =
9122 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009123 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009124
9125 touch();
9126
9127 mTouchWindow->assertNoEvents();
9128}
9129
9130TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009131 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9132 const sp<FakeWindowHandle>& w =
9133 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009134 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009135
9136 touch();
9137
9138 w->assertNoEvents();
9139}
9140
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009141TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009142 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009143 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009144
9145 touch();
9146
9147 mTouchWindow->consumeAnyMotionDown();
9148}
9149
9150TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009151 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009152 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009153 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009154 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009155
9156 touch({PointF{100, 100}});
9157
9158 mTouchWindow->consumeAnyMotionDown();
9159}
9160
9161TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009162 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009163 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009164 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009165
9166 touch();
9167
9168 mTouchWindow->consumeAnyMotionDown();
9169}
9170
9171TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9172 const sp<FakeWindowHandle>& w =
9173 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009174 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009175
9176 touch();
9177
9178 mTouchWindow->consumeAnyMotionDown();
9179}
9180
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009181TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9182 const sp<FakeWindowHandle>& w =
9183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009184 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009185
9186 touch();
9187
9188 w->assertNoEvents();
9189}
9190
9191/**
9192 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9193 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9194 * window, the occluding window will still receive ACTION_OUTSIDE event.
9195 */
9196TEST_F(InputDispatcherUntrustedTouchesTest,
9197 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9198 const sp<FakeWindowHandle>& w =
9199 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009200 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009201 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009202
9203 touch();
9204
9205 w->consumeMotionOutside();
9206}
9207
9208TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9209 const sp<FakeWindowHandle>& w =
9210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009211 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009212 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009213
9214 touch();
9215
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009216 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009217}
9218
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009219TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009220 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9222 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009223 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009224
9225 touch();
9226
9227 mTouchWindow->consumeAnyMotionDown();
9228}
9229
9230TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9231 const sp<FakeWindowHandle>& w =
9232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9233 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009234 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009235
9236 touch();
9237
9238 mTouchWindow->consumeAnyMotionDown();
9239}
9240
9241TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009242 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009243 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9244 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009245 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009246
9247 touch();
9248
9249 mTouchWindow->assertNoEvents();
9250}
9251
9252TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9253 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9254 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009255 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9256 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009257 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009258 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9259 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009260 mDispatcher->onWindowInfosChanged(
9261 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009262
9263 touch();
9264
9265 mTouchWindow->assertNoEvents();
9266}
9267
9268TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9269 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9270 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009271 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9272 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009273 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009274 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9275 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009276 mDispatcher->onWindowInfosChanged(
9277 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009278
9279 touch();
9280
9281 mTouchWindow->consumeAnyMotionDown();
9282}
9283
9284TEST_F(InputDispatcherUntrustedTouchesTest,
9285 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9286 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009287 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9288 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009289 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009290 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9291 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009292 mDispatcher->onWindowInfosChanged(
9293 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009294
9295 touch();
9296
9297 mTouchWindow->consumeAnyMotionDown();
9298}
9299
9300TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9301 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009302 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9303 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009304 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009305 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9306 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009307 mDispatcher->onWindowInfosChanged(
9308 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009309
9310 touch();
9311
9312 mTouchWindow->assertNoEvents();
9313}
9314
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009315TEST_F(InputDispatcherUntrustedTouchesTest,
9316 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9317 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009318 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9319 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009320 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009321 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9322 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009323 mDispatcher->onWindowInfosChanged(
9324 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009325
9326 touch();
9327
9328 mTouchWindow->assertNoEvents();
9329}
9330
9331TEST_F(InputDispatcherUntrustedTouchesTest,
9332 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9333 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009334 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9335 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009336 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009337 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9338 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009339 mDispatcher->onWindowInfosChanged(
9340 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009341
9342 touch();
9343
9344 mTouchWindow->consumeAnyMotionDown();
9345}
9346
9347TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9348 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009349 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9350 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009351 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009352
9353 touch();
9354
9355 mTouchWindow->consumeAnyMotionDown();
9356}
9357
9358TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9359 const sp<FakeWindowHandle>& w =
9360 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009361 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009362
9363 touch();
9364
9365 mTouchWindow->consumeAnyMotionDown();
9366}
9367
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009368TEST_F(InputDispatcherUntrustedTouchesTest,
9369 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9370 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9371 const sp<FakeWindowHandle>& w =
9372 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009373 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009374
9375 touch();
9376
9377 mTouchWindow->assertNoEvents();
9378}
9379
9380TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9381 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9382 const sp<FakeWindowHandle>& w =
9383 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009384 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009385
9386 touch();
9387
9388 mTouchWindow->consumeAnyMotionDown();
9389}
9390
9391TEST_F(InputDispatcherUntrustedTouchesTest,
9392 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9393 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9394 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009395 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9396 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009397 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009398
9399 touch();
9400
9401 mTouchWindow->consumeAnyMotionDown();
9402}
9403
9404TEST_F(InputDispatcherUntrustedTouchesTest,
9405 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9406 const sp<FakeWindowHandle>& w1 =
9407 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9408 OPACITY_BELOW_THRESHOLD);
9409 const sp<FakeWindowHandle>& w2 =
9410 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9411 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009412 mDispatcher->onWindowInfosChanged(
9413 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009414
9415 touch();
9416
9417 mTouchWindow->assertNoEvents();
9418}
9419
9420/**
9421 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9422 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9423 * (which alone would result in allowing touches) does not affect the blocking behavior.
9424 */
9425TEST_F(InputDispatcherUntrustedTouchesTest,
9426 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9427 const sp<FakeWindowHandle>& wB =
9428 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9429 OPACITY_BELOW_THRESHOLD);
9430 const sp<FakeWindowHandle>& wC =
9431 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9432 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009433 mDispatcher->onWindowInfosChanged(
9434 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009435
9436 touch();
9437
9438 mTouchWindow->assertNoEvents();
9439}
9440
9441/**
9442 * This test is testing that a window from a different UID but with same application token doesn't
9443 * block the touch. Apps can share the application token for close UI collaboration for example.
9444 */
9445TEST_F(InputDispatcherUntrustedTouchesTest,
9446 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9447 const sp<FakeWindowHandle>& w =
9448 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9449 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009450 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009451
9452 touch();
9453
9454 mTouchWindow->consumeAnyMotionDown();
9455}
9456
arthurhungb89ccb02020-12-30 16:19:01 +08009457class InputDispatcherDragTests : public InputDispatcherTest {
9458protected:
9459 std::shared_ptr<FakeApplicationHandle> mApp;
9460 sp<FakeWindowHandle> mWindow;
9461 sp<FakeWindowHandle> mSecondWindow;
9462 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009463 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009464 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9465 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009466
9467 void SetUp() override {
9468 InputDispatcherTest::SetUp();
9469 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009470 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009471 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009472
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009473 mSecondWindow =
9474 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009475 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009476
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009477 mSpyWindow =
9478 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009479 mSpyWindow->setSpy(true);
9480 mSpyWindow->setTrustedOverlay(true);
9481 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9482
arthurhungb89ccb02020-12-30 16:19:01 +08009483 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009484 mDispatcher->onWindowInfosChanged(
9485 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9486 {},
9487 0,
9488 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009489 }
9490
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009491 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9492 switch (fromSource) {
9493 case AINPUT_SOURCE_TOUCHSCREEN:
9494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009495 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009496 ADISPLAY_ID_DEFAULT, {50, 50}))
9497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9498 break;
9499 case AINPUT_SOURCE_STYLUS:
9500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009501 injectMotionEvent(*mDispatcher,
9502 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9503 AINPUT_SOURCE_STYLUS)
9504 .buttonState(
9505 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9506 .pointer(PointerBuilder(0, ToolType::STYLUS)
9507 .x(50)
9508 .y(50))
9509 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009510 break;
9511 case AINPUT_SOURCE_MOUSE:
9512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009513 injectMotionEvent(*mDispatcher,
9514 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9515 AINPUT_SOURCE_MOUSE)
9516 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9517 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9518 ToolType::MOUSE)
9519 .x(50)
9520 .y(50))
9521 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009522 break;
9523 default:
9524 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9525 }
arthurhungb89ccb02020-12-30 16:19:01 +08009526
9527 // Window should receive motion event.
9528 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009529 // Spy window should also receive motion event
9530 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009531 }
9532
9533 // Start performing drag, we will create a drag window and transfer touch to it.
9534 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9535 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009536 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009537 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009538 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009539 }
arthurhungb89ccb02020-12-30 16:19:01 +08009540
9541 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009542 mDragWindow =
9543 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009544 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009545 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9546 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9547 {},
9548 0,
9549 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009550
9551 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009552 bool transferred =
9553 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009554 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009555 if (transferred) {
9556 mWindow->consumeMotionCancel();
9557 mDragWindow->consumeMotionDown();
9558 }
9559 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009560 }
9561};
9562
9563TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009564 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009565
9566 // Move on window.
9567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009568 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009569 ADISPLAY_ID_DEFAULT, {50, 50}))
9570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9571 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9572 mWindow->consumeDragEvent(false, 50, 50);
9573 mSecondWindow->assertNoEvents();
9574
9575 // Move to another window.
9576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009577 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009578 ADISPLAY_ID_DEFAULT, {150, 50}))
9579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9580 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9581 mWindow->consumeDragEvent(true, 150, 50);
9582 mSecondWindow->consumeDragEvent(false, 50, 50);
9583
9584 // Move back to original window.
9585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009586 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009587 ADISPLAY_ID_DEFAULT, {50, 50}))
9588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9589 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9590 mWindow->consumeDragEvent(false, 50, 50);
9591 mSecondWindow->consumeDragEvent(true, -50, 50);
9592
9593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009594 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9595 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9597 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9598 mWindow->assertNoEvents();
9599 mSecondWindow->assertNoEvents();
9600}
9601
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009602TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009603 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009604
9605 // No cancel event after drag start
9606 mSpyWindow->assertNoEvents();
9607
9608 const MotionEvent secondFingerDownEvent =
9609 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9610 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009611 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9612 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009613 .build();
9614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009615 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009616 InputEventInjectionSync::WAIT_FOR_RESULT))
9617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9618
9619 // Receives cancel for first pointer after next pointer down
9620 mSpyWindow->consumeMotionCancel();
9621 mSpyWindow->consumeMotionDown();
9622
9623 mSpyWindow->assertNoEvents();
9624}
9625
arthurhungf452d0b2021-01-06 00:19:52 +08009626TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009627 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009628
9629 // Move on window.
9630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009631 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009632 ADISPLAY_ID_DEFAULT, {50, 50}))
9633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9634 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9635 mWindow->consumeDragEvent(false, 50, 50);
9636 mSecondWindow->assertNoEvents();
9637
9638 // Move to another window.
9639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009640 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009641 ADISPLAY_ID_DEFAULT, {150, 50}))
9642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9643 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9644 mWindow->consumeDragEvent(true, 150, 50);
9645 mSecondWindow->consumeDragEvent(false, 50, 50);
9646
9647 // drop to another window.
9648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009649 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009650 {150, 50}))
9651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9652 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009653 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009654 mWindow->assertNoEvents();
9655 mSecondWindow->assertNoEvents();
9656}
9657
arthurhung6d4bed92021-03-17 11:59:33 +08009658TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009659 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009660
9661 // Move on window and keep button pressed.
9662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009663 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009664 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9665 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009666 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009667 .build()))
9668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9669 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9670 mWindow->consumeDragEvent(false, 50, 50);
9671 mSecondWindow->assertNoEvents();
9672
9673 // Move to another window and release button, expect to drop item.
9674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009675 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009676 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9677 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009679 .build()))
9680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9681 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9682 mWindow->assertNoEvents();
9683 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009684 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009685
9686 // nothing to the window.
9687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009688 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009689 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9690 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009691 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009692 .build()))
9693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9694 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9695 mWindow->assertNoEvents();
9696 mSecondWindow->assertNoEvents();
9697}
9698
Arthur Hung54745652022-04-20 07:17:41 +00009699TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009700 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009701
9702 // Set second window invisible.
9703 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009704 mDispatcher->onWindowInfosChanged(
9705 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009706
9707 // Move on window.
9708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009709 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009710 ADISPLAY_ID_DEFAULT, {50, 50}))
9711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9712 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9713 mWindow->consumeDragEvent(false, 50, 50);
9714 mSecondWindow->assertNoEvents();
9715
9716 // Move to another window.
9717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009718 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009719 ADISPLAY_ID_DEFAULT, {150, 50}))
9720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9721 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9722 mWindow->consumeDragEvent(true, 150, 50);
9723 mSecondWindow->assertNoEvents();
9724
9725 // drop to another window.
9726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009727 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009728 {150, 50}))
9729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9730 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009731 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009732 mWindow->assertNoEvents();
9733 mSecondWindow->assertNoEvents();
9734}
9735
Arthur Hung54745652022-04-20 07:17:41 +00009736TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009737 // Ensure window could track pointerIds if it didn't support split touch.
9738 mWindow->setPreventSplitting(true);
9739
Arthur Hung54745652022-04-20 07:17:41 +00009740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009741 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009742 {50, 50}))
9743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9744 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9745
9746 const MotionEvent secondFingerDownEvent =
9747 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9748 .displayId(ADISPLAY_ID_DEFAULT)
9749 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009750 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9751 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009752 .build();
9753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009754 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009755 InputEventInjectionSync::WAIT_FOR_RESULT))
9756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009757 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009758
9759 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009760 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009761}
9762
9763TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9764 // First down on second window.
9765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009767 {150, 50}))
9768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9769
9770 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9771
9772 // Second down on first window.
9773 const MotionEvent secondFingerDownEvent =
9774 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9775 .displayId(ADISPLAY_ID_DEFAULT)
9776 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009777 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9778 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009779 .build();
9780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009781 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009782 InputEventInjectionSync::WAIT_FOR_RESULT))
9783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9784 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9785
9786 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009787 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009788
9789 // Move on window.
9790 const MotionEvent secondFingerMoveEvent =
9791 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9792 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009793 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9794 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009795 .build();
9796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009797 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009798 InputEventInjectionSync::WAIT_FOR_RESULT));
9799 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9800 mWindow->consumeDragEvent(false, 50, 50);
9801 mSecondWindow->consumeMotionMove();
9802
9803 // Release the drag pointer should perform drop.
9804 const MotionEvent secondFingerUpEvent =
9805 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9806 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009807 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9808 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009809 .build();
9810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009811 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009812 InputEventInjectionSync::WAIT_FOR_RESULT));
9813 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009814 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009815 mWindow->assertNoEvents();
9816 mSecondWindow->consumeMotionMove();
9817}
9818
Arthur Hung3915c1f2022-05-31 07:17:17 +00009819TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009820 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009821
9822 // Update window of second display.
9823 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009824 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009825 mDispatcher->onWindowInfosChanged(
9826 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9827 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9828 {},
9829 0,
9830 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009831
9832 // Let second display has a touch state.
9833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009834 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009835 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9836 AINPUT_SOURCE_TOUCHSCREEN)
9837 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009838 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009839 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009840 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009841 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009842 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009843 mDispatcher->onWindowInfosChanged(
9844 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9845 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9846 {},
9847 0,
9848 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009849
9850 // Move on window.
9851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009852 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009853 ADISPLAY_ID_DEFAULT, {50, 50}))
9854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9855 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9856 mWindow->consumeDragEvent(false, 50, 50);
9857 mSecondWindow->assertNoEvents();
9858
9859 // Move to another window.
9860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009862 ADISPLAY_ID_DEFAULT, {150, 50}))
9863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9864 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9865 mWindow->consumeDragEvent(true, 150, 50);
9866 mSecondWindow->consumeDragEvent(false, 50, 50);
9867
9868 // drop to another window.
9869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009870 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009871 {150, 50}))
9872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9873 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009874 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009875 mWindow->assertNoEvents();
9876 mSecondWindow->assertNoEvents();
9877}
9878
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009879TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9880 startDrag(true, AINPUT_SOURCE_MOUSE);
9881 // Move on window.
9882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009883 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009884 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9885 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009886 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009887 .x(50)
9888 .y(50))
9889 .build()))
9890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9891 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9892 mWindow->consumeDragEvent(false, 50, 50);
9893 mSecondWindow->assertNoEvents();
9894
9895 // Move to another window.
9896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009897 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009898 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9899 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009900 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009901 .x(150)
9902 .y(50))
9903 .build()))
9904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9905 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9906 mWindow->consumeDragEvent(true, 150, 50);
9907 mSecondWindow->consumeDragEvent(false, 50, 50);
9908
9909 // drop to another window.
9910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009911 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009912 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9913 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009914 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009915 .x(150)
9916 .y(50))
9917 .build()))
9918 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9919 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009920 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009921 mWindow->assertNoEvents();
9922 mSecondWindow->assertNoEvents();
9923}
9924
Linnan Li5af92f92023-07-14 14:36:22 +08009925/**
9926 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9927 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9928 */
9929TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9930 // Down on second window
9931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9932 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9933 {150, 50}))
9934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9935
9936 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9937 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9938
9939 // Down on first window
9940 const MotionEvent secondFingerDownEvent =
9941 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9942 .displayId(ADISPLAY_ID_DEFAULT)
9943 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9944 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9945 .build();
9946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9947 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9948 InputEventInjectionSync::WAIT_FOR_RESULT))
9949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9950 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9951 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9952 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9953
9954 // Start drag on first window
9955 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9956
9957 // Trigger cancel
9958 mDispatcher->cancelCurrentTouch();
9959 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9960 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9961 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9962
9963 ASSERT_TRUE(mDispatcher->waitForIdle());
9964 // The D&D finished with nullptr
9965 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9966
9967 // Remove drag window
9968 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9969
9970 // Inject a simple gesture, ensure dispatcher not crashed
9971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9972 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9973 PointF{50, 50}))
9974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9975 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9976
9977 const MotionEvent moveEvent =
9978 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9979 .displayId(ADISPLAY_ID_DEFAULT)
9980 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9981 .build();
9982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9983 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9984 InputEventInjectionSync::WAIT_FOR_RESULT))
9985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9986 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9987
9988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9989 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9990 {50, 50}))
9991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9992 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9993}
9994
Vishnu Nair062a8672021-09-03 16:07:44 -07009995class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9996
9997TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009999 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10000 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010001 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010002 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10003 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010004 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010005 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010006 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010007
10008 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010009 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010010 window->assertNoEvents();
10011
Prabir Pradhan678438e2023-04-13 19:32:51 +000010012 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10013 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010014 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10015 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010016 window->assertNoEvents();
10017
10018 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010019 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010021
Prabir Pradhan678438e2023-04-13 19:32:51 +000010022 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010023 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10024
Prabir Pradhan678438e2023-04-13 19:32:51 +000010025 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10026 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010027 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10028 window->assertNoEvents();
10029}
10030
10031TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10032 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10033 std::make_shared<FakeApplicationHandle>();
10034 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010035 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10036 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010037 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010038 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010039 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10042 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010043 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010044 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010045 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10046 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010047 mDispatcher->onWindowInfosChanged(
10048 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010049 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010050 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010051
10052 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010053 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010054 window->assertNoEvents();
10055
Prabir Pradhan678438e2023-04-13 19:32:51 +000010056 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10057 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010058 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10059 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010060 window->assertNoEvents();
10061
10062 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010063 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010064 mDispatcher->onWindowInfosChanged(
10065 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010066
Prabir Pradhan678438e2023-04-13 19:32:51 +000010067 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010068 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10069
Prabir Pradhan678438e2023-04-13 19:32:51 +000010070 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10071 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010072 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10073 window->assertNoEvents();
10074}
10075
10076TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10077 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10078 std::make_shared<FakeApplicationHandle>();
10079 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010080 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10081 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010082 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010083 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010084 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010086 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10087 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010088 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010089 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010090 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10091 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010092 mDispatcher->onWindowInfosChanged(
10093 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010094 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010095 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010096
10097 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010098 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010099 window->assertNoEvents();
10100
Prabir Pradhan678438e2023-04-13 19:32:51 +000010101 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10102 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010103 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10104 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010105 window->assertNoEvents();
10106
10107 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010108 mDispatcher->onWindowInfosChanged(
10109 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010110
Prabir Pradhan678438e2023-04-13 19:32:51 +000010111 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010112 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10113
Prabir Pradhan678438e2023-04-13 19:32:51 +000010114 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10115 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010116 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10117 window->assertNoEvents();
10118}
10119
Antonio Kantekf16f2832021-09-28 04:39:20 +000010120class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10121protected:
10122 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010123 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010124 sp<FakeWindowHandle> mWindow;
10125 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010126 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010127
10128 void SetUp() override {
10129 InputDispatcherTest::SetUp();
10130
10131 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010132 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010133 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010134 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010135 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010136 mSecondWindow =
10137 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010138 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010139 mThirdWindow =
10140 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10141 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10142 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010143
10144 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010145 mDispatcher->onWindowInfosChanged(
10146 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10147 {},
10148 0,
10149 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010150 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010151 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010152
Antonio Kantek15beb512022-06-13 22:35:41 +000010153 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010154 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010155 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010156 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10157 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010158 mThirdWindow->assertNoEvents();
10159 }
10160
10161 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10162 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010163 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010164 SECOND_DISPLAY_ID)) {
10165 mWindow->assertNoEvents();
10166 mSecondWindow->assertNoEvents();
10167 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010168 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010169 }
10170
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010171 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010172 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010173 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10174 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010175 mWindow->consumeTouchModeEvent(inTouchMode);
10176 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010177 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010178 }
10179};
10180
Antonio Kantek26defcf2022-02-08 01:12:27 +000010181TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010182 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010183 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10184 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010185 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010186}
10187
Antonio Kantek26defcf2022-02-08 01:12:27 +000010188TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10189 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010190 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010191 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010192 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010193 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010194 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010195 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010196 mWindow->assertNoEvents();
10197 mSecondWindow->assertNoEvents();
10198}
10199
10200TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10201 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010202 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010203 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010204 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010205 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010206 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010207}
10208
Antonio Kantekf16f2832021-09-28 04:39:20 +000010209TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010210 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010211 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10212 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010213 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010214 mWindow->assertNoEvents();
10215 mSecondWindow->assertNoEvents();
10216}
10217
Antonio Kantek15beb512022-06-13 22:35:41 +000010218TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10219 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10220 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10221 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010222 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010223 mWindow->assertNoEvents();
10224 mSecondWindow->assertNoEvents();
10225 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10226}
10227
Antonio Kantek48710e42022-03-24 14:19:30 -070010228TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10229 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10231 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010232 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10233 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10234
10235 // Then remove focus.
10236 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010237 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010238
10239 // Assert that caller can switch touch mode by owning one of the last interacted window.
10240 const WindowInfo& windowInfo = *mWindow->getInfo();
10241 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10242 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010243 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010244}
10245
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010246class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10247public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010248 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010249 std::shared_ptr<FakeApplicationHandle> application =
10250 std::make_shared<FakeApplicationHandle>();
10251 std::string name = "Fake Spy ";
10252 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010253 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10254 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010255 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010256 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010257 return spy;
10258 }
10259
10260 sp<FakeWindowHandle> createForeground() {
10261 std::shared_ptr<FakeApplicationHandle> application =
10262 std::make_shared<FakeApplicationHandle>();
10263 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010264 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10265 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010266 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010267 return window;
10268 }
10269
10270private:
10271 int mSpyCount{0};
10272};
10273
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010274using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010275/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010276 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10277 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010278TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010279 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010280 ScopedSilentDeath _silentDeath;
10281
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010282 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010283 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010285 ".* not a trusted overlay");
10286}
10287
10288/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010289 * Input injection into a display with a spy window but no foreground windows should succeed.
10290 */
10291TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010292 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010293 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010294
10295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010296 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010297 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10298 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10299}
10300
10301/**
10302 * Verify the order in which different input windows receive events. The touched foreground window
10303 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10304 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10305 * receive events before ones belows it.
10306 *
10307 * Here, we set up a scenario with four windows in the following Z order from the top:
10308 * spy1, spy2, window, spy3.
10309 * We then inject an event and verify that the foreground "window" receives it first, followed by
10310 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10311 * window.
10312 */
10313TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10314 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010315 auto spy1 = createSpy();
10316 auto spy2 = createSpy();
10317 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010318 mDispatcher->onWindowInfosChanged(
10319 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010320 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10321 const size_t numChannels = channels.size();
10322
Michael Wright8e9a8562022-02-09 13:44:29 +000010323 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010324 if (!epollFd.ok()) {
10325 FAIL() << "Failed to create epoll fd";
10326 }
10327
10328 for (size_t i = 0; i < numChannels; i++) {
10329 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10330 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10331 FAIL() << "Failed to add fd to epoll";
10332 }
10333 }
10334
10335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010336 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10338
10339 std::vector<size_t> eventOrder;
10340 std::vector<struct epoll_event> events(numChannels);
10341 for (;;) {
10342 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10343 (100ms).count());
10344 if (nFds < 0) {
10345 FAIL() << "Failed to call epoll_wait";
10346 }
10347 if (nFds == 0) {
10348 break; // epoll_wait timed out
10349 }
10350 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010351 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010352 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010353 channels[i]->consumeMotionDown();
10354 }
10355 }
10356
10357 // Verify the order in which the events were received.
10358 EXPECT_EQ(3u, eventOrder.size());
10359 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10360 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10361 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10362}
10363
10364/**
10365 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10366 */
10367TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10368 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010369 auto spy = createSpy();
10370 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010371 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010372
10373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010374 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010375 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10376 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10377 spy->assertNoEvents();
10378}
10379
10380/**
10381 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10382 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10383 * to the window.
10384 */
10385TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10386 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010387 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010388 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010389 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010390
10391 // Inject an event outside the spy window's touchable region.
10392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010393 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10395 window->consumeMotionDown();
10396 spy->assertNoEvents();
10397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010398 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010399 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10400 window->consumeMotionUp();
10401 spy->assertNoEvents();
10402
10403 // Inject an event inside the spy window's touchable region.
10404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010405 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010406 {5, 10}))
10407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10408 window->consumeMotionDown();
10409 spy->consumeMotionDown();
10410}
10411
10412/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010413 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010414 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010415 */
10416TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10417 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010418 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010419 auto spy = createSpy();
10420 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010421 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010422 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010423 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010424
10425 // Inject an event outside the spy window's frame and touchable region.
10426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010427 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010428 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010429 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10430 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010431 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010432}
10433
10434/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010435 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10436 * pointers that are down within its bounds.
10437 */
10438TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10439 auto windowLeft = createForeground();
10440 windowLeft->setFrame({0, 0, 100, 200});
10441 auto windowRight = createForeground();
10442 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010443 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010444 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010445 mDispatcher->onWindowInfosChanged(
10446 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010447
10448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010449 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010450 {50, 50}))
10451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10452 windowLeft->consumeMotionDown();
10453 spy->consumeMotionDown();
10454
10455 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010456 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010457 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010458 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10459 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010460 .build();
10461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010462 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010463 InputEventInjectionSync::WAIT_FOR_RESULT))
10464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10465 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010466 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010467}
10468
10469/**
10470 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10471 * the spy should receive the second pointer with ACTION_DOWN.
10472 */
10473TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10474 auto window = createForeground();
10475 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010476 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010477 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010478 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010479
10480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010481 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010482 {50, 50}))
10483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10484 window->consumeMotionDown();
10485 spyRight->assertNoEvents();
10486
10487 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010488 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010489 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010490 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10491 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010492 .build();
10493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010494 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010495 InputEventInjectionSync::WAIT_FOR_RESULT))
10496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010497 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010498 spyRight->consumeMotionDown();
10499}
10500
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010501/**
10502 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10503 * windows should be allowed to control split touch.
10504 */
10505TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010506 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010507 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010508 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010509 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010510
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010511 auto window = createForeground();
10512 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010513
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010514 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010515
10516 // First finger down, no window touched.
10517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010518 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010519 {100, 200}))
10520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10521 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10522 window->assertNoEvents();
10523
10524 // Second finger down on window, the window should receive touch down.
10525 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010526 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010527 .displayId(ADISPLAY_ID_DEFAULT)
10528 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010529 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10530 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010531 .build();
10532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010533 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010534 InputEventInjectionSync::WAIT_FOR_RESULT))
10535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10536
10537 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010538 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010539}
10540
10541/**
10542 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10543 * do not receive key events.
10544 */
10545TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010546 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010547 spy->setFocusable(false);
10548
10549 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010550 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010551 setFocusedWindow(window);
10552 window->consumeFocusEvent(true);
10553
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010555 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10556 window->consumeKeyDown(ADISPLAY_ID_NONE);
10557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010559 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10560 window->consumeKeyUp(ADISPLAY_ID_NONE);
10561
10562 spy->assertNoEvents();
10563}
10564
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010565using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10566
10567/**
10568 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10569 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10570 */
10571TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10572 auto window = createForeground();
10573 auto spy1 = createSpy();
10574 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010575 mDispatcher->onWindowInfosChanged(
10576 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010577
10578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010579 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10581 window->consumeMotionDown();
10582 spy1->consumeMotionDown();
10583 spy2->consumeMotionDown();
10584
10585 // Pilfer pointers from the second spy window.
10586 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10587 spy2->assertNoEvents();
10588 spy1->consumeMotionCancel();
10589 window->consumeMotionCancel();
10590
10591 // The rest of the gesture should only be sent to the second spy window.
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010594 ADISPLAY_ID_DEFAULT))
10595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10596 spy2->consumeMotionMove();
10597 spy1->assertNoEvents();
10598 window->assertNoEvents();
10599}
10600
10601/**
10602 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10603 * in the middle of the gesture.
10604 */
10605TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10606 auto window = createForeground();
10607 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010608 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010609
10610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010611 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10613 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10614 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10615
10616 window->releaseChannel();
10617
10618 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10619
10620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010621 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10623 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10624}
10625
10626/**
10627 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10628 * the spy, but not to any other windows.
10629 */
10630TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10631 auto spy = createSpy();
10632 auto window = createForeground();
10633
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010634 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010635
10636 // First finger down on the window and the spy.
10637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010638 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010639 {100, 200}))
10640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10641 spy->consumeMotionDown();
10642 window->consumeMotionDown();
10643
10644 // Spy window pilfers the pointers.
10645 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10646 window->consumeMotionCancel();
10647
10648 // Second finger down on the window and spy, but the window should not receive the pointer down.
10649 const MotionEvent secondFingerDownEvent =
10650 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10651 .displayId(ADISPLAY_ID_DEFAULT)
10652 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010653 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10654 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010655 .build();
10656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010657 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010658 InputEventInjectionSync::WAIT_FOR_RESULT))
10659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10660
Harry Cutts33476232023-01-30 19:57:29 +000010661 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010662
10663 // Third finger goes down outside all windows, so injection should fail.
10664 const MotionEvent thirdFingerDownEvent =
10665 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10666 .displayId(ADISPLAY_ID_DEFAULT)
10667 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010668 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10669 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10670 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010671 .build();
10672 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010673 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010674 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010675 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010676
10677 spy->assertNoEvents();
10678 window->assertNoEvents();
10679}
10680
10681/**
10682 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10683 */
10684TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10685 auto spy = createSpy();
10686 spy->setFrame(Rect(0, 0, 100, 100));
10687 auto window = createForeground();
10688 window->setFrame(Rect(0, 0, 200, 200));
10689
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010690 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010691
10692 // First finger down on the window only
10693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010694 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010695 {150, 150}))
10696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10697 window->consumeMotionDown();
10698
10699 // Second finger down on the spy and window
10700 const MotionEvent secondFingerDownEvent =
10701 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10702 .displayId(ADISPLAY_ID_DEFAULT)
10703 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010704 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10705 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010706 .build();
10707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010708 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010709 InputEventInjectionSync::WAIT_FOR_RESULT))
10710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10711 spy->consumeMotionDown();
10712 window->consumeMotionPointerDown(1);
10713
10714 // Third finger down on the spy and window
10715 const MotionEvent thirdFingerDownEvent =
10716 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10717 .displayId(ADISPLAY_ID_DEFAULT)
10718 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010719 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10720 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10721 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010722 .build();
10723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010724 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010725 InputEventInjectionSync::WAIT_FOR_RESULT))
10726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10727 spy->consumeMotionPointerDown(1);
10728 window->consumeMotionPointerDown(2);
10729
10730 // Spy window pilfers the pointers.
10731 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010732 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10733 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010734
10735 spy->assertNoEvents();
10736 window->assertNoEvents();
10737}
10738
10739/**
10740 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10741 * other windows should be canceled. If this results in the cancellation of all pointers for some
10742 * window, then that window should receive ACTION_CANCEL.
10743 */
10744TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10745 auto spy = createSpy();
10746 spy->setFrame(Rect(0, 0, 100, 100));
10747 auto window = createForeground();
10748 window->setFrame(Rect(0, 0, 200, 200));
10749
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010750 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010751
10752 // First finger down on both spy and window
10753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010755 {10, 10}))
10756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10757 window->consumeMotionDown();
10758 spy->consumeMotionDown();
10759
10760 // Second finger down on the spy and window
10761 const MotionEvent secondFingerDownEvent =
10762 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10763 .displayId(ADISPLAY_ID_DEFAULT)
10764 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010765 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10766 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010767 .build();
10768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010769 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010770 InputEventInjectionSync::WAIT_FOR_RESULT))
10771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10772 spy->consumeMotionPointerDown(1);
10773 window->consumeMotionPointerDown(1);
10774
10775 // Spy window pilfers the pointers.
10776 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10777 window->consumeMotionCancel();
10778
10779 spy->assertNoEvents();
10780 window->assertNoEvents();
10781}
10782
10783/**
10784 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10785 * be sent to other windows
10786 */
10787TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10788 auto spy = createSpy();
10789 spy->setFrame(Rect(0, 0, 100, 100));
10790 auto window = createForeground();
10791 window->setFrame(Rect(0, 0, 200, 200));
10792
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010793 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010794
10795 // First finger down on both window and spy
10796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010797 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010798 {10, 10}))
10799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10800 window->consumeMotionDown();
10801 spy->consumeMotionDown();
10802
10803 // Spy window pilfers the pointers.
10804 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10805 window->consumeMotionCancel();
10806
10807 // Second finger down on the window only
10808 const MotionEvent secondFingerDownEvent =
10809 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10810 .displayId(ADISPLAY_ID_DEFAULT)
10811 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010812 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10813 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010814 .build();
10815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010816 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010817 InputEventInjectionSync::WAIT_FOR_RESULT))
10818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10819 window->consumeMotionDown();
10820 window->assertNoEvents();
10821
10822 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10823 spy->consumeMotionMove();
10824 spy->assertNoEvents();
10825}
10826
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010827/**
10828 * A window on the left and a window on the right. Also, a spy window that's above all of the
10829 * windows, and spanning both left and right windows.
10830 * Send simultaneous motion streams from two different devices, one to the left window, and another
10831 * to the right window.
10832 * Pilfer from spy window.
10833 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10834 */
10835TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10836 sp<FakeWindowHandle> spy = createSpy();
10837 spy->setFrame(Rect(0, 0, 200, 200));
10838 sp<FakeWindowHandle> leftWindow = createForeground();
10839 leftWindow->setFrame(Rect(0, 0, 100, 100));
10840
10841 sp<FakeWindowHandle> rightWindow = createForeground();
10842 rightWindow->setFrame(Rect(100, 0, 200, 100));
10843
10844 constexpr int32_t stylusDeviceId = 1;
10845 constexpr int32_t touchDeviceId = 2;
10846
10847 mDispatcher->onWindowInfosChanged(
10848 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10849
10850 // Stylus down on left window and spy
10851 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10852 .deviceId(stylusDeviceId)
10853 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10854 .build());
10855 leftWindow->consumeMotionEvent(
10856 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10857 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10858
10859 // Finger down on right window and spy - but spy already has stylus
10860 mDispatcher->notifyMotion(
10861 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10862 .deviceId(touchDeviceId)
10863 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10864 .build());
10865 rightWindow->consumeMotionEvent(
10866 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010867 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010868
10869 // Act: pilfer from spy. Spy is currently receiving touch events.
10870 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010871 leftWindow->consumeMotionEvent(
10872 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010873 rightWindow->consumeMotionEvent(
10874 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10875
10876 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10877 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10878 .deviceId(stylusDeviceId)
10879 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10880 .build());
10881 mDispatcher->notifyMotion(
10882 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10883 .deviceId(touchDeviceId)
10884 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10885 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010886 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010887
10888 spy->assertNoEvents();
10889 leftWindow->assertNoEvents();
10890 rightWindow->assertNoEvents();
10891}
10892
Prabir Pradhand65552b2021-10-07 11:23:50 -070010893class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10894public:
10895 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10896 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10897 std::make_shared<FakeApplicationHandle>();
10898 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010899 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10900 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010901 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010902 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010903 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010904 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010905 overlay->setTrustedOverlay(true);
10906
10907 std::shared_ptr<FakeApplicationHandle> application =
10908 std::make_shared<FakeApplicationHandle>();
10909 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010910 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10911 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010912 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010913 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010914
10915 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010916 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010917 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010918 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010919 return {std::move(overlay), std::move(window)};
10920 }
10921
10922 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010923 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010924 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010925 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010926 }
10927
10928 void sendStylusEvent(int32_t action) {
10929 NotifyMotionArgs motionArgs =
10930 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10931 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010932 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010933 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010934 }
10935};
10936
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010937using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10938
10939TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010940 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010941 ScopedSilentDeath _silentDeath;
10942
Prabir Pradhand65552b2021-10-07 11:23:50 -070010943 auto [overlay, window] = setupStylusOverlayScenario();
10944 overlay->setTrustedOverlay(false);
10945 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010946 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10947 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010948 ".* not a trusted overlay");
10949}
10950
10951TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10952 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010953 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010954
10955 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10956 overlay->consumeMotionDown();
10957 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10958 overlay->consumeMotionUp();
10959
10960 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10961 window->consumeMotionDown();
10962 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10963 window->consumeMotionUp();
10964
10965 overlay->assertNoEvents();
10966 window->assertNoEvents();
10967}
10968
10969TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10970 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010971 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010972 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010973
10974 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10975 overlay->consumeMotionDown();
10976 window->consumeMotionDown();
10977 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10978 overlay->consumeMotionUp();
10979 window->consumeMotionUp();
10980
10981 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10982 window->consumeMotionDown();
10983 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10984 window->consumeMotionUp();
10985
10986 overlay->assertNoEvents();
10987 window->assertNoEvents();
10988}
10989
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010990/**
10991 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10992 * The scenario is as follows:
10993 * - The stylus interceptor overlay is configured as a spy window.
10994 * - The stylus interceptor spy receives the start of a new stylus gesture.
10995 * - It pilfers pointers and then configures itself to no longer be a spy.
10996 * - The stylus interceptor continues to receive the rest of the gesture.
10997 */
10998TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10999 auto [overlay, window] = setupStylusOverlayScenario();
11000 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011001 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011002
11003 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11004 overlay->consumeMotionDown();
11005 window->consumeMotionDown();
11006
11007 // The interceptor pilfers the pointers.
11008 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11009 window->consumeMotionCancel();
11010
11011 // The interceptor configures itself so that it is no longer a spy.
11012 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011013 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011014
11015 // It continues to receive the rest of the stylus gesture.
11016 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11017 overlay->consumeMotionMove();
11018 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11019 overlay->consumeMotionUp();
11020
11021 window->assertNoEvents();
11022}
11023
Prabir Pradhan5735a322022-04-11 17:23:34 +000011024struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011025 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011026 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011027 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11028 std::unique_ptr<InputDispatcher>& mDispatcher;
11029
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011030 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011031 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11032
11033 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011034 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011035 ADISPLAY_ID_DEFAULT, {100, 200},
11036 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11037 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11038 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11039 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11040 }
11041
11042 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011043 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011044 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011045 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011046 mPolicyFlags);
11047 }
11048
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011049 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011050 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11051 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011052 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11053 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011054 window->setOwnerInfo(mPid, mUid);
11055 return window;
11056 }
11057};
11058
11059using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11060
11061TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011062 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011063 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011064 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011065
11066 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11067 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11068 window->consumeMotionDown();
11069
11070 setFocusedWindow(window);
11071 window->consumeFocusEvent(true);
11072
11073 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11074 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11075 window->consumeKeyDown(ADISPLAY_ID_NONE);
11076}
11077
11078TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011079 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011080 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011081 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011082
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011083 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011084 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11085 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11086
11087 setFocusedWindow(window);
11088 window->consumeFocusEvent(true);
11089
11090 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11091 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11092 window->assertNoEvents();
11093}
11094
11095TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011096 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011097 auto window = owner.createWindow("Owned window");
11098 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011099 spy->setSpy(true);
11100 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011101 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011102
11103 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11104 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11105 spy->consumeMotionDown();
11106 window->consumeMotionDown();
11107}
11108
11109TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011110 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011111 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011112
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011113 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011114 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011115 randosSpy->setSpy(true);
11116 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011117 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011118
11119 // The event is targeted at owner's window, so injection should succeed, but the spy should
11120 // not receive the event.
11121 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11122 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11123 randosSpy->assertNoEvents();
11124 window->consumeMotionDown();
11125}
11126
11127TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011128 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011129 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011130
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011131 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011132 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011133 randosSpy->setSpy(true);
11134 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011135 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011136
11137 // A user that has injection permission can inject into any window.
11138 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011139 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011140 ADISPLAY_ID_DEFAULT));
11141 randosSpy->consumeMotionDown();
11142 window->consumeMotionDown();
11143
11144 setFocusedWindow(randosSpy);
11145 randosSpy->consumeFocusEvent(true);
11146
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011147 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011148 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11149 window->assertNoEvents();
11150}
11151
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011152TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011153 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011154 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011155
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011156 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011157 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011158 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11159 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011160 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011161
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011162 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011163 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11164 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11165 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011166 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011167}
11168
Garfield Tane84e6f92019-08-29 17:28:41 -070011169} // namespace android::inputdispatcher