blob: b73fa0e7557221f535637ed4fc8436e1c99c00cc [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);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001055 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001056 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001057 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001058 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001059 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001060 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1061 ADD_FAILURE() << "Received focus event, hasFocus = "
1062 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001063 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001064 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1065 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1066 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001067 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1069 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1070 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 }
1072 FAIL() << mName.c_str()
1073 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001074 }
1075
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001076 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080private:
1081 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001082 PreallocatedInputEventFactory mEventFactory;
1083
1084 std::string mName;
1085};
1086
chaviw3277faf2021-05-19 16:45:23 -05001087class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001088public:
1089 static const int32_t WIDTH = 600;
1090 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001091
Chris Yea209fde2020-07-22 13:54:51 -07001092 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001093 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001094 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001095 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001097 base::Result<std::unique_ptr<InputChannel>> channel =
1098 dispatcher->createInputChannel(name);
1099 token = (*channel)->getConnectionToken();
1100 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
1103 inputApplicationHandle->updateInfo();
1104 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1105
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001106 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001107 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001108 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001109 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001110 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001111 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001112 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001113 mInfo.globalScaleFactor = 1.0;
1114 mInfo.touchableRegion.clear();
1115 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001116 mInfo.ownerPid = WINDOW_PID;
1117 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001118 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001119 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001120 }
1121
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001122 sp<FakeWindowHandle> clone(int32_t displayId) {
1123 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1124 handle->mInfo = mInfo;
1125 handle->mInfo.displayId = displayId;
1126 handle->mInfo.id = sId++;
1127 handle->mInputReceiver = mInputReceiver;
1128 return handle;
1129 }
1130
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001131 void setTouchable(bool touchable) {
1132 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1133 }
chaviwd1c23182019-12-20 18:44:56 -08001134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setFocusable(bool focusable) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1137 }
1138
1139 void setVisible(bool visible) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1141 }
Vishnu Nair958da932020-08-21 17:12:37 -07001142
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001143 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 }
1146
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001147 void setPaused(bool paused) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1149 }
1150
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001151 void setPreventSplitting(bool preventSplitting) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001153 }
1154
1155 void setSlippery(bool slippery) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1157 }
1158
1159 void setWatchOutsideTouch(bool watchOutside) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1161 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001162
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001163 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1164
1165 void setInterceptsStylus(bool interceptsStylus) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1167 }
1168
1169 void setDropInput(bool dropInput) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1171 }
1172
1173 void setDropInputIfObscured(bool dropInputIfObscured) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1175 }
1176
1177 void setNoInputChannel(bool noInputChannel) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1179 }
1180
Josep del Riob3981622023-04-18 15:49:45 +00001181 void setDisableUserActivity(bool disableUserActivity) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1183 }
1184
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001185 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1186
chaviw3277faf2021-05-19 16:45:23 -05001187 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001188
Bernardo Rufino7393d172021-02-26 13:56:11 +00001189 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1190
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001191 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001192 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001193 mInfo.touchableRegion.clear();
1194 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001195
1196 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1197 ui::Transform translate;
1198 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1199 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001200 }
1201
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001202 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1203
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 void setIsWallpaper(bool isWallpaper) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1206 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001207
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001208 void setDupTouchToWallpaper(bool hasWallpaper) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1210 }
chaviwd1c23182019-12-20 18:44:56 -08001211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setTrustedOverlay(bool trustedOverlay) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1214 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001215
chaviw9eaa22c2020-07-01 16:21:27 -07001216 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1217 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1218 }
1219
1220 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001221
yunho.shinf4a80b82020-11-16 21:13:57 +09001222 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1223
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001224 KeyEvent* consumeKey(bool handled = true) {
1225 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001226 if (event == nullptr) {
1227 ADD_FAILURE() << "Consume failed : no event";
1228 return nullptr;
1229 }
1230 if (event->getType() != InputEventType::KEY) {
1231 ADD_FAILURE() << "Instead of key event, got " << *event;
1232 return nullptr;
1233 }
1234 return static_cast<KeyEvent*>(event);
1235 }
1236
1237 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1238 KeyEvent* keyEvent = consumeKey();
1239 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1240 ASSERT_THAT(*keyEvent, matcher);
1241 }
1242
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001243 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001244 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 }
1246
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001247 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001248 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 }
1250
Svet Ganov5d3bc372020-01-26 23:11:07 -08001251 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001252 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001253 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1254 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 }
1256
1257 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001258 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001259 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1260 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001265 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1266 }
1267
1268 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1269 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001270 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 expectedFlags);
1272 }
1273
Svet Ganov5d3bc372020-01-26 23:11:07 -08001274 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001275 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1276 int32_t expectedFlags = 0) {
1277 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1278 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 }
1281
1282 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedFlags = 0) {
1284 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1285 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 }
1288
1289 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001290 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001291 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001292 expectedFlags);
1293 }
1294
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001295 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1296 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001298 expectedFlags);
1299 }
1300
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001301 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1302 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001303 MotionEvent* motionEvent = consumeMotion();
1304 ASSERT_NE(nullptr, motionEvent);
1305 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1306 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1307 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001308 }
1309
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001310 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1311 ASSERT_NE(mInputReceiver, nullptr)
1312 << "Cannot consume events from a window with no receiver";
1313 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1314 }
1315
Prabir Pradhan99987712020-11-10 18:43:05 -08001316 void consumeCaptureEvent(bool hasCapture) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeCaptureEvent(hasCapture);
1320 }
1321
Prabir Pradhan5893d362023-11-17 04:30:40 +00001322 const MotionEvent& consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001323 MotionEvent* motionEvent = consumeMotion();
Prabir Pradhan5893d362023-11-17 04:30:40 +00001324 if (nullptr == motionEvent) {
1325 LOG(FATAL) << "Did not get a motion event, but expected " << matcher;
1326 }
1327 EXPECT_THAT(*motionEvent, matcher);
1328 return *motionEvent;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001329 }
1330
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001332 std::optional<int32_t> expectedDisplayId,
1333 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1335 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1336 expectedFlags);
1337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001367 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001368 if (mInputReceiver == nullptr) {
1369 return nullptr;
1370 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001371 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001372 }
1373
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001375 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001376 if (event == nullptr) {
1377 ADD_FAILURE() << "Consume failed : no event";
1378 return nullptr;
1379 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001380 if (event->getType() != InputEventType::MOTION) {
1381 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001382 return nullptr;
1383 }
1384 return static_cast<MotionEvent*>(event);
1385 }
1386
Arthur Hungb92218b2018-08-14 12:00:21 +08001387 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001388 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001389 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001390 return; // Can't receive events if the window does not have input channel
1391 }
1392 ASSERT_NE(nullptr, mInputReceiver)
1393 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001394 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001395 }
1396
chaviwaf87b3e2019-10-01 16:59:28 -07001397 sp<IBinder> getToken() { return mInfo.token; }
1398
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001399 const std::string& getName() { return mName; }
1400
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001401 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001402 mInfo.ownerPid = ownerPid;
1403 mInfo.ownerUid = ownerUid;
1404 }
1405
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001406 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001407
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001408 void destroyReceiver() { mInputReceiver = nullptr; }
1409
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001410 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1411
chaviwd1c23182019-12-20 18:44:56 -08001412private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001413 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001414 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001415 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001416 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001417 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001418};
1419
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001420std::atomic<int32_t> FakeWindowHandle::sId{1};
1421
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001422class FakeMonitorReceiver {
1423public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001424 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1425 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001426
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001427 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428
1429 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001430 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1431 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001432 }
1433
1434 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001435 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001436 }
1437
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001438 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001439
1440 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001441 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1442 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001443 }
1444
1445 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001446 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1447 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001448 }
1449
1450 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001451 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1452 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001453 }
1454
1455 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001456 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001457 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1458 WithDisplayId(expectedDisplayId),
1459 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1460 }
1461
1462 void consumeMotionPointerDown(int32_t pointerIdx) {
1463 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1464 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001465 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1466 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467 }
1468
1469 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001470 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001471 }
1472
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001473 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001474
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001475 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476
1477private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001478 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001479};
1480
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001481static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001482 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001483 int32_t displayId = ADISPLAY_ID_NONE,
1484 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001485 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001486 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001487 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001488 KeyEvent event;
1489 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1490
1491 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001492 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001493 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1494 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001495
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496 if (!allowKeyRepeat) {
1497 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1498 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001499 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001501}
1502
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001503static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1504 InputEventInjectionResult result =
1505 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1506 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1507 if (result != InputEventInjectionResult::TIMED_OUT) {
1508 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1509 }
1510}
1511
1512static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001514 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001515}
1516
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001517// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1518// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1519// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001520static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1521 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001522 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001523 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001524 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001525}
1526
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001527static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001529 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001530}
1531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001533 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001534 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001535 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001536 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001537 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1538 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001539}
1540
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001541static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001542 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1543 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001544 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001545 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1546 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001547 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001548 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001549 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001550 MotionEventBuilder motionBuilder =
1551 MotionEventBuilder(action, source)
1552 .displayId(displayId)
1553 .eventTime(eventTime)
1554 .rawXCursorPosition(cursorPosition.x)
1555 .rawYCursorPosition(cursorPosition.y)
1556 .pointer(
1557 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1558 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1559 motionBuilder.downTime(eventTime);
1560 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001561
1562 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001563 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1564 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001565}
1566
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001567static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1568 int32_t displayId,
1569 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001570 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001571}
1572
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001573static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1574 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001575 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001576 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001577}
1578
Jackal Guof9696682018-10-05 12:23:23 +08001579static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1580 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1581 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001582 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001583 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1584 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001585
1586 return args;
1587}
1588
Josep del Riob3981622023-04-18 15:49:45 +00001589static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1590 int32_t displayId = ADISPLAY_ID_NONE) {
1591 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1592 // Define a valid key event.
1593 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001594 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001595 currentTime);
1596
1597 return args;
1598}
1599
1600static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1601 int32_t displayId = ADISPLAY_ID_NONE) {
1602 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1603 // Define a valid key event.
1604 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001605 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001606 AMETA_NONE, currentTime);
1607
1608 return args;
1609}
1610
Prabir Pradhan678438e2023-04-13 19:32:51 +00001611[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1612 int32_t displayId,
1613 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001614 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001615 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1616 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1617 }
1618
chaviwd1c23182019-12-20 18:44:56 -08001619 PointerProperties pointerProperties[pointerCount];
1620 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001621
chaviwd1c23182019-12-20 18:44:56 -08001622 for (size_t i = 0; i < pointerCount; i++) {
1623 pointerProperties[i].clear();
1624 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001625 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001626
chaviwd1c23182019-12-20 18:44:56 -08001627 pointerCoords[i].clear();
1628 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1629 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1630 }
Jackal Guof9696682018-10-05 12:23:23 +08001631
1632 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1633 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001634 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001635 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1636 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001637 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001638 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001639 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001640 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001641
1642 return args;
1643}
1644
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001645static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1646 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1647}
1648
chaviwd1c23182019-12-20 18:44:56 -08001649static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1650 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1651}
1652
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001653static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1654 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001655 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001656}
1657
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001658} // namespace
1659
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001660/**
1661 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1662 * broken channel.
1663 */
1664TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1666 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001667 sp<FakeWindowHandle>::make(application, mDispatcher,
1668 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001671
1672 // Window closes its channel, but the window remains.
1673 window->destroyReceiver();
1674 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1675}
1676
Arthur Hungb92218b2018-08-14 12:00:21 +08001677TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001679 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1680 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001681
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001684 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001686
1687 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001688 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001689}
1690
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001691TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1694 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001695
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001696 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001697 // Inject a MotionEvent to an unknown display.
1698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001699 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1701
1702 // Window should receive motion event.
1703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1704}
1705
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001707 * Calling onWindowInfosChanged once should not cause any issues.
1708 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709 * called twice.
1710 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001711TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1714 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722
1723 // Window should receive motion event.
1724 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1725}
1726
1727/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001729 */
1730TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1733 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001735
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001740 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742
1743 // Window should receive motion event.
1744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1745}
1746
Arthur Hungb92218b2018-08-14 12:00:21 +08001747// The foreground window should receive the first touch down event.
1748TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001750 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001751 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001752 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001753 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001755 mDispatcher->onWindowInfosChanged(
1756 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001760
1761 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001762 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001763 windowSecond->assertNoEvents();
1764}
1765
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001766/**
1767 * Two windows: A top window, and a wallpaper behind the window.
1768 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1769 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001770 * 1. foregroundWindow <-- dup touch to wallpaper
1771 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001772 */
1773TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1775 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001776 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001777 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001778 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001779 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001780 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001782 mDispatcher->onWindowInfosChanged(
1783 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001785 injectMotionEvent(*mDispatcher,
1786 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1787 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1788 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001789 << "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 Vishniakoud908f5a2023-11-16 10:25:12 -08001796 injectMotionEvent(*mDispatcher,
1797 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1798 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1799 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1801
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001802 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001803 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1804
1805 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001806 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001807 foregroundWindow->consumeMotionCancel();
1808 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1809 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1810}
1811
1812/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001813 * Two fingers down on the window, and lift off the first finger.
1814 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1815 * contains a single pointer.
1816 */
1817TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1819 sp<FakeWindowHandle> window =
1820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1821
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001823 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1825 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1826 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001827 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001828 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1829 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1830 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1831 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001832 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1834 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1835 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1836 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001837 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1838 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1839 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1840
1841 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001843 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1844 window->consumeMotionEvent(
1845 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1846}
1847
1848/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001849 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1850 * with the following differences:
1851 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1852 * clean up the connection.
1853 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1854 * Ensure that there's no crash in the dispatcher.
1855 */
1856TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1858 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001859 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001860 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001863 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged(
1866 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001868 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869 {100, 200}))
1870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1871
1872 // Both foreground window and its wallpaper should receive the touch down
1873 foregroundWindow->consumeMotionDown();
1874 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001877 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001878 ADISPLAY_ID_DEFAULT, {110, 200}))
1879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1880
1881 foregroundWindow->consumeMotionMove();
1882 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1883
1884 // Wallpaper closes its channel, but the window remains.
1885 wallpaperWindow->destroyReceiver();
1886 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1887
1888 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1889 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001890 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001891 foregroundWindow->consumeMotionCancel();
1892}
1893
Arthur Hungc539dbb2022-12-08 07:45:36 +00001894class ShouldSplitTouchFixture : public InputDispatcherTest,
1895 public ::testing::WithParamInterface<bool> {};
1896INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1897 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001898/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 * A single window that receives touch (on top), and a wallpaper window underneath it.
1900 * The top window gets a multitouch gesture.
1901 * Ensure that wallpaper gets the same gesture.
1902 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001903TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001905 sp<FakeWindowHandle> foregroundWindow =
1906 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1907 foregroundWindow->setDupTouchToWallpaper(true);
1908 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909
1910 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001911 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001912 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001914 mDispatcher->onWindowInfosChanged(
1915 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916
1917 // Touch down on top window
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920 {100, 100}))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922
1923 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001924 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1926
1927 // Second finger down on the top window
1928 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001929 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 .build();
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 InputEventInjectionSync::WAIT_FOR_RESULT))
1937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1938
Harry Cutts33476232023-01-30 19:57:29 +00001939 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1940 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001942
1943 const MotionEvent secondFingerUpEvent =
1944 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1945 .displayId(ADISPLAY_ID_DEFAULT)
1946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001947 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1948 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001949 .build();
1950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001951 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952 InputEventInjectionSync::WAIT_FOR_RESULT))
1953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1954 foregroundWindow->consumeMotionPointerUp(0);
1955 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1956
1957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001958 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001959 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1960 AINPUT_SOURCE_TOUCHSCREEN)
1961 .displayId(ADISPLAY_ID_DEFAULT)
1962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001963 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001964 .x(100)
1965 .y(100))
1966 .build(),
1967 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1970 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971}
1972
1973/**
1974 * Two windows: a window on the left and window on the right.
1975 * A third window, wallpaper, is behind both windows, and spans both top windows.
1976 * The first touch down goes to the left window. A second pointer touches down on the right window.
1977 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1978 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1979 * ACTION_POINTER_DOWN(1).
1980 */
1981TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1983 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001984 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001986 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987
1988 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001989 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001991 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992
1993 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001994 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001996 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001998 mDispatcher->onWindowInfosChanged(
1999 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2000 {},
2001 0,
2002 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003
2004 // Touch down on left window
2005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002006 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 {100, 100}))
2008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2009
2010 // Both foreground window and its wallpaper should receive the touch down
2011 leftWindow->consumeMotionDown();
2012 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2013
2014 // Second finger down on the right window
2015 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002016 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002018 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2019 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 .build();
2021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002022 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 InputEventInjectionSync::WAIT_FOR_RESULT))
2024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2025
2026 leftWindow->consumeMotionMove();
2027 // Since the touch is split, right window gets ACTION_DOWN
2028 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002029 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 expectedWallpaperFlags);
2031
2032 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002033 mDispatcher->onWindowInfosChanged(
2034 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035 leftWindow->consumeMotionCancel();
2036 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2037 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2038
2039 // The pointer that's still down on the right window moves, and goes to the right window only.
2040 // As far as the dispatcher's concerned though, both pointers are still present.
2041 const MotionEvent secondFingerMoveEvent =
2042 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2043 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002044 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2045 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046 .build();
2047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002048 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 InputEventInjectionSync::WAIT_FOR_RESULT));
2050 rightWindow->consumeMotionMove();
2051
2052 leftWindow->assertNoEvents();
2053 rightWindow->assertNoEvents();
2054 wallpaperWindow->assertNoEvents();
2055}
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057/**
2058 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2059 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2060 * The right window should receive ACTION_DOWN.
2061 */
2062TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064 sp<FakeWindowHandle> leftWindow =
2065 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2066 leftWindow->setFrame(Rect(0, 0, 200, 200));
2067 leftWindow->setDupTouchToWallpaper(true);
2068 leftWindow->setSlippery(true);
2069
2070 sp<FakeWindowHandle> rightWindow =
2071 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2072 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002073
2074 sp<FakeWindowHandle> wallpaperWindow =
2075 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2076 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002077
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002078 mDispatcher->onWindowInfosChanged(
2079 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2080 {},
2081 0,
2082 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002083
Arthur Hungc539dbb2022-12-08 07:45:36 +00002084 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002086 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002087 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089
2090 // Both foreground window and its wallpaper should receive the touch down
2091 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002092 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2093
Arthur Hungc539dbb2022-12-08 07:45:36 +00002094 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002096 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002097 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2099
Arthur Hungc539dbb2022-12-08 07:45:36 +00002100 leftWindow->consumeMotionCancel();
2101 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2102 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002103}
2104
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002105/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2107 * interactive, it might stop sending this flag.
2108 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2109 * to have a consistent input stream.
2110 *
2111 * Test procedure:
2112 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2113 * DOWN (new gesture).
2114 *
2115 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2116 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2117 *
2118 * We technically just need a single window here, but we are using two windows (spy on top and a
2119 * regular window below) to emulate the actual situation where it happens on the device.
2120 */
2121TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2123 sp<FakeWindowHandle> spyWindow =
2124 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2125 spyWindow->setFrame(Rect(0, 0, 200, 200));
2126 spyWindow->setTrustedOverlay(true);
2127 spyWindow->setSpy(true);
2128
2129 sp<FakeWindowHandle> window =
2130 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2131 window->setFrame(Rect(0, 0, 200, 200));
2132
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002133 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
2136 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002137 mDispatcher->notifyMotion(
2138 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139 .deviceId(touchDeviceId)
2140 .policyFlags(DEFAULT_POLICY_FLAGS)
2141 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2142 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002143
Prabir Pradhan678438e2023-04-13 19:32:51 +00002144 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2145 .deviceId(touchDeviceId)
2146 .policyFlags(DEFAULT_POLICY_FLAGS)
2147 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2148 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2149 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002150 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2151 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2152 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2153 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2154
2155 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002156 mDispatcher->notifyMotion(
2157 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2158 .deviceId(touchDeviceId)
2159 .policyFlags(0)
2160 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2161 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2162 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002163 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2164 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2165
2166 // We don't need to reset the device to reproduce the issue, but the reset event typically
2167 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002168 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002169
2170 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002171 mDispatcher->notifyMotion(
2172 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2173 .deviceId(touchDeviceId)
2174 .policyFlags(DEFAULT_POLICY_FLAGS)
2175 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2176 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002177 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2178 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2179
2180 // No more events
2181 spyWindow->assertNoEvents();
2182 window->assertNoEvents();
2183}
2184
2185/**
Linnan Li907ae732023-09-05 17:14:21 +08002186 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2187 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2188 * interactive, it might stop sending this flag.
2189 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2190 * the consistency of the hover event in this case.
2191 *
2192 * Test procedure:
2193 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2194 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2195 *
2196 * We expect to receive two full streams of hover events.
2197 */
2198TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2200
2201 sp<FakeWindowHandle> window =
2202 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2203 window->setFrame(Rect(0, 0, 300, 300));
2204
2205 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2206
2207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2208 .policyFlags(DEFAULT_POLICY_FLAGS)
2209 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2210 .build());
2211 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2212
2213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2214 .policyFlags(DEFAULT_POLICY_FLAGS)
2215 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2216 .build());
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2218
2219 // Send hover exit without the default policy flags.
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2221 .policyFlags(0)
2222 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2223 .build());
2224
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2226
2227 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2228 // right event.
2229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2230 .policyFlags(DEFAULT_POLICY_FLAGS)
2231 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2232 .build());
2233 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2234
2235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2236 .policyFlags(DEFAULT_POLICY_FLAGS)
2237 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2238 .build());
2239 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2240
2241 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2242 .policyFlags(DEFAULT_POLICY_FLAGS)
2243 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2244 .build());
2245 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2246}
2247
2248/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002249 * Two windows: a window on the left and a window on the right.
2250 * Mouse is hovered from the right window into the left window.
2251 * Next, we tap on the left window, where the cursor was last seen.
2252 * The second tap is done onto the right window.
2253 * The mouse and tap are from two different devices.
2254 * We technically don't need to set the downtime / eventtime for these events, but setting these
2255 * explicitly helps during debugging.
2256 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2257 * In the buggy implementation, a tap on the right window would cause a crash.
2258 */
2259TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2261 sp<FakeWindowHandle> leftWindow =
2262 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2263 leftWindow->setFrame(Rect(0, 0, 200, 200));
2264
2265 sp<FakeWindowHandle> rightWindow =
2266 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2267 rightWindow->setFrame(Rect(200, 0, 400, 200));
2268
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002269 mDispatcher->onWindowInfosChanged(
2270 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2272 // stale.
2273 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2274 const int32_t mouseDeviceId = 6;
2275 const int32_t touchDeviceId = 4;
2276 // Move the cursor from right
2277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002278 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002279 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2280 AINPUT_SOURCE_MOUSE)
2281 .deviceId(mouseDeviceId)
2282 .downTime(baseTime + 10)
2283 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002284 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002285 .build()));
2286 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2287
2288 // .. to the left window
2289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002290 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002291 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2292 AINPUT_SOURCE_MOUSE)
2293 .deviceId(mouseDeviceId)
2294 .downTime(baseTime + 10)
2295 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002296 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002297 .build()));
2298 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2299 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2300 // Now tap the left window
2301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002302 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002303 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2304 AINPUT_SOURCE_TOUCHSCREEN)
2305 .deviceId(touchDeviceId)
2306 .downTime(baseTime + 40)
2307 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002308 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002309 .build()));
2310 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2311 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2312
2313 // release tap
2314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002315 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002316 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2317 AINPUT_SOURCE_TOUCHSCREEN)
2318 .deviceId(touchDeviceId)
2319 .downTime(baseTime + 40)
2320 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002321 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002322 .build()));
2323 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2324
2325 // Tap the window on the right
2326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002327 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002328 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2329 AINPUT_SOURCE_TOUCHSCREEN)
2330 .deviceId(touchDeviceId)
2331 .downTime(baseTime + 60)
2332 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002333 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002334 .build()));
2335 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2336
2337 // release tap
2338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002340 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2341 AINPUT_SOURCE_TOUCHSCREEN)
2342 .deviceId(touchDeviceId)
2343 .downTime(baseTime + 60)
2344 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002345 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002346 .build()));
2347 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2348
2349 // No more events
2350 leftWindow->assertNoEvents();
2351 rightWindow->assertNoEvents();
2352}
2353
2354/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002355 * Start hovering in a window. While this hover is still active, make another window appear on top.
2356 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2357 * While the top window is present, the hovering is stopped.
2358 * Later, hovering gets resumed again.
2359 * Ensure that new hover gesture is handled correctly.
2360 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2361 * to the window that's currently being hovered over.
2362 */
2363TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2365 sp<FakeWindowHandle> window =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2367 window->setFrame(Rect(0, 0, 200, 200));
2368
2369 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002370 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002371
2372 // Start hovering in the window
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2374 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2375 .build());
2376 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2377
2378 // Now, an obscuring window appears!
2379 sp<FakeWindowHandle> obscuringWindow =
2380 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2381 ADISPLAY_ID_DEFAULT,
2382 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2383 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2384 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2385 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2386 obscuringWindow->setNoInputChannel(true);
2387 obscuringWindow->setFocusable(false);
2388 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002389 mDispatcher->onWindowInfosChanged(
2390 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002391
2392 // While this new obscuring window is present, the hovering is stopped
2393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2395 .build());
2396 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2397
2398 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002399 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002400
2401 // And a new hover gesture starts.
2402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2403 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2404 .build());
2405 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2406}
2407
2408/**
2409 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2410 * the obscuring window.
2411 */
2412TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2414 sp<FakeWindowHandle> window =
2415 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2416 window->setFrame(Rect(0, 0, 200, 200));
2417
2418 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002419 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // Start hovering in the window
2422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2424 .build());
2425 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2426
2427 // Now, an obscuring window appears!
2428 sp<FakeWindowHandle> obscuringWindow =
2429 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2430 ADISPLAY_ID_DEFAULT,
2431 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2432 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2433 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2434 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2435 obscuringWindow->setNoInputChannel(true);
2436 obscuringWindow->setFocusable(false);
2437 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002438 mDispatcher->onWindowInfosChanged(
2439 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002440
2441 // While this new obscuring window is present, the hovering continues. The event can't go to the
2442 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2443 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2444 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2445 .build());
2446 obscuringWindow->assertNoEvents();
2447 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2448
2449 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002450 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002451
2452 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2453 // so it should generate a HOVER_ENTER
2454 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2455 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2456 .build());
2457 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2458
2459 // Now the MOVE should be getting dispatched normally
2460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2461 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2462 .build());
2463 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2464}
2465
2466/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002467 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2468 * events are delivered to the window.
2469 */
2470TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2472 sp<FakeWindowHandle> window =
2473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2474 window->setFrame(Rect(0, 0, 200, 200));
2475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2476
2477 // Start hovering in the window
2478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2479 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2480 .build());
2481 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2482
2483 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2484 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2485 .build());
2486 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2487
2488 // Scroll with the mouse
2489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2490 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2491 .build());
2492 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2493}
2494
2495using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2496
2497/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002498 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2499 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002500 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002501TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2503 sp<FakeWindowHandle> window =
2504 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2505 window->setFrame(Rect(0, 0, 200, 200));
2506
2507 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2508
2509 constexpr int32_t touchDeviceId = 4;
2510 constexpr int32_t stylusDeviceId = 2;
2511
2512 // Stylus down
2513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2514 .deviceId(stylusDeviceId)
2515 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2516 .build());
2517 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2518
2519 // Touch down
2520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2521 .deviceId(touchDeviceId)
2522 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2523 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524
2525 // Touch move
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2527 .deviceId(touchDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2529 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002530 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002531
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002532 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2536 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002537 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2538 WithCoords(101, 111)));
2539
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002540 window->assertNoEvents();
2541}
2542
2543/**
2544 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002545 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002546 * Similar test as above, but with added SPY window.
2547 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002548TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2550 sp<FakeWindowHandle> window =
2551 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2552 sp<FakeWindowHandle> spyWindow =
2553 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2554 spyWindow->setFrame(Rect(0, 0, 200, 200));
2555 spyWindow->setTrustedOverlay(true);
2556 spyWindow->setSpy(true);
2557 window->setFrame(Rect(0, 0, 200, 200));
2558
2559 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2560
2561 constexpr int32_t touchDeviceId = 4;
2562 constexpr int32_t stylusDeviceId = 2;
2563
2564 // Stylus down
2565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2566 .deviceId(stylusDeviceId)
2567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2568 .build());
2569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2570 spyWindow->consumeMotionEvent(
2571 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2572
2573 // Touch down
2574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2575 .deviceId(touchDeviceId)
2576 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2577 .build());
2578
2579 // Touch move
2580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2581 .deviceId(touchDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2583 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002584
2585 // Touch is ignored because stylus is already down
2586
2587 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2589 .deviceId(stylusDeviceId)
2590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2591 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002592 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2593 WithCoords(101, 111)));
2594 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2595 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002596
2597 window->assertNoEvents();
2598 spyWindow->assertNoEvents();
2599}
2600
2601/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002602 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002603 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002604 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002605TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2607 sp<FakeWindowHandle> window =
2608 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2609 window->setFrame(Rect(0, 0, 200, 200));
2610
2611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2612
2613 constexpr int32_t touchDeviceId = 4;
2614 constexpr int32_t stylusDeviceId = 2;
2615
2616 // Stylus down on the window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2618 .deviceId(stylusDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620 .build());
2621 window->consumeMotionEvent(
2622 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2623
2624 // Touch down on window
2625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
2627 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2628 .build());
2629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2630 .deviceId(touchDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2632 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002633
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002634 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002636 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2638 .deviceId(stylusDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2640 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002641 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2642 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002644 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2646 .deviceId(touchDeviceId)
2647 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2648 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002649 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002650}
2651
2652/**
2653 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002654 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002656TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2658 sp<FakeWindowHandle> window =
2659 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2660 window->setFrame(Rect(0, 0, 200, 200));
2661
2662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2663
2664 constexpr int32_t touchDeviceId = 4;
2665 constexpr int32_t stylusDeviceId = 2;
2666
2667 // Touch down on window
2668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2669 .deviceId(touchDeviceId)
2670 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2671 .build());
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2675 .build());
2676 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2678
2679 // Stylus hover on the window
2680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2681 .deviceId(stylusDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2683 .build());
2684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2685 .deviceId(stylusDeviceId)
2686 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2687 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002688 // Stylus hover movement causes touch to be canceled
2689 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2690 WithCoords(141, 146)));
2691 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2692 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2693 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2694 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002696 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002697 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2698 .deviceId(touchDeviceId)
2699 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2700 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002701
2702 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002703}
2704
2705/**
2706 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2707 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2708 * become active.
2709 */
2710TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2712 sp<FakeWindowHandle> window =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2714 window->setFrame(Rect(0, 0, 200, 200));
2715
2716 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2717
2718 constexpr int32_t stylusDeviceId1 = 3;
2719 constexpr int32_t stylusDeviceId2 = 5;
2720
2721 // Touch down on window
2722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2723 .deviceId(stylusDeviceId1)
2724 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2725 .build());
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId1)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2729 .build());
2730 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2731 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2732
2733 // Second stylus down
2734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2735 .deviceId(stylusDeviceId2)
2736 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2737 .build());
2738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2739 .deviceId(stylusDeviceId2)
2740 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2741 .build());
2742
2743 // First stylus is canceled, second one takes over.
2744 window->consumeMotionEvent(
2745 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2746 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2747 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2748
2749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2750 .deviceId(stylusDeviceId1)
2751 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2752 .build());
2753 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002754 window->assertNoEvents();
2755}
2756
2757/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002758 * One window. Touch down on the window. Then, stylus down on the window from another device.
2759 * Ensure that is canceled, because stylus down should be preferred over touch.
2760 */
2761TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2763 sp<FakeWindowHandle> window =
2764 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2765 window->setFrame(Rect(0, 0, 200, 200));
2766
2767 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2768
2769 constexpr int32_t touchDeviceId = 4;
2770 constexpr int32_t stylusDeviceId = 2;
2771
2772 // Touch down on window
2773 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2774 .deviceId(touchDeviceId)
2775 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2776 .build());
2777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2778 .deviceId(touchDeviceId)
2779 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2780 .build());
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2783
2784 // Stylus down on the window
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2791
2792 // Subsequent stylus movements are delivered correctly
2793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2794 .deviceId(stylusDeviceId)
2795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2796 .build());
2797 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2798 WithCoords(101, 111)));
2799}
2800
2801/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002802 * Two windows: a window on the left and a window on the right.
2803 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2804 * down. Then, on the left window, also place second touch pointer down.
2805 * This test tries to reproduce a crash.
2806 * In the buggy implementation, second pointer down on the left window would cause a crash.
2807 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002808TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2810 sp<FakeWindowHandle> leftWindow =
2811 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2812 leftWindow->setFrame(Rect(0, 0, 200, 200));
2813
2814 sp<FakeWindowHandle> rightWindow =
2815 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2816 rightWindow->setFrame(Rect(200, 0, 400, 200));
2817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002818 mDispatcher->onWindowInfosChanged(
2819 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002820
2821 const int32_t touchDeviceId = 4;
2822 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002823
2824 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2826 .deviceId(mouseDeviceId)
2827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2828 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002829 leftWindow->consumeMotionEvent(
2830 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2831
2832 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2834 .deviceId(mouseDeviceId)
2835 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2837 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002838
2839 leftWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2841 leftWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2843
Prabir Pradhan678438e2023-04-13 19:32:51 +00002844 mDispatcher->notifyMotion(
2845 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2846 .deviceId(mouseDeviceId)
2847 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2848 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2849 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2850 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002851 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2852
2853 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2855 .deviceId(touchDeviceId)
2856 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2857 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002858 leftWindow->assertNoEvents();
2859
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2861
2862 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002863 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2864 .deviceId(touchDeviceId)
2865 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2866 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2867 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002868 // Since this is now a new splittable pointer going down on the left window, and it's coming
2869 // from a different device, the current gesture in the left window (pointer down) should first
2870 // be canceled.
2871 leftWindow->consumeMotionEvent(
2872 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 leftWindow->consumeMotionEvent(
2874 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2875 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2876 // current implementation.
2877 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2878 rightWindow->consumeMotionEvent(
2879 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2880
2881 leftWindow->assertNoEvents();
2882 rightWindow->assertNoEvents();
2883}
2884
2885/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002886 * Two windows: a window on the left and a window on the right.
2887 * Mouse is hovered on the left window and stylus is hovered on the right window.
2888 */
2889TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2891 sp<FakeWindowHandle> leftWindow =
2892 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2893 leftWindow->setFrame(Rect(0, 0, 200, 200));
2894
2895 sp<FakeWindowHandle> rightWindow =
2896 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2897 rightWindow->setFrame(Rect(200, 0, 400, 200));
2898
2899 mDispatcher->onWindowInfosChanged(
2900 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2901
2902 const int32_t stylusDeviceId = 3;
2903 const int32_t mouseDeviceId = 6;
2904
2905 // Start hovering over the left window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2907 .deviceId(mouseDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2909 .build());
2910 leftWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2912
2913 // Stylus hovered on right window
2914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2915 .deviceId(stylusDeviceId)
2916 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2917 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002918 rightWindow->consumeMotionEvent(
2919 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2920
2921 // Subsequent HOVER_MOVE events are dispatched correctly.
2922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2923 .deviceId(mouseDeviceId)
2924 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2925 .build());
2926 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002927 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002928
2929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2930 .deviceId(stylusDeviceId)
2931 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2932 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002934 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935
2936 leftWindow->assertNoEvents();
2937 rightWindow->assertNoEvents();
2938}
2939
2940/**
2941 * Three windows: a window on the left and a window on the right.
2942 * And a spy window that's positioned above all of them.
2943 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2944 * Check the stream that's received by the spy.
2945 */
2946TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2948
2949 sp<FakeWindowHandle> spyWindow =
2950 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2951 spyWindow->setFrame(Rect(0, 0, 400, 400));
2952 spyWindow->setTrustedOverlay(true);
2953 spyWindow->setSpy(true);
2954
2955 sp<FakeWindowHandle> leftWindow =
2956 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2957 leftWindow->setFrame(Rect(0, 0, 200, 200));
2958
2959 sp<FakeWindowHandle> rightWindow =
2960 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2961
2962 rightWindow->setFrame(Rect(200, 0, 400, 200));
2963
2964 mDispatcher->onWindowInfosChanged(
2965 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2966
2967 const int32_t stylusDeviceId = 1;
2968 const int32_t touchDeviceId = 2;
2969
2970 // Stylus down on the left window
2971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2972 .deviceId(stylusDeviceId)
2973 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2974 .build());
2975 leftWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977 spyWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2979
2980 // Touch down on the right window
2981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2982 .deviceId(touchDeviceId)
2983 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2984 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002985 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 rightWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002988
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 // Spy window does not receive touch events, because stylus events take precedence, and it
2990 // already has an active stylus gesture.
2991
2992 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2994 .deviceId(stylusDeviceId)
2995 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2996 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002997 leftWindow->consumeMotionEvent(
2998 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2999 spyWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003002 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3004 .deviceId(touchDeviceId)
3005 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3006 .build());
3007 rightWindow->consumeMotionEvent(
3008 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003009
3010 spyWindow->assertNoEvents();
3011 leftWindow->assertNoEvents();
3012 rightWindow->assertNoEvents();
3013}
3014
3015/**
3016 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3017 * both.
3018 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003019 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003020 * At the same time, left and right should be getting independent streams of hovering and touch,
3021 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003022 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003023TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3025
3026 sp<FakeWindowHandle> spyWindow =
3027 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3028 spyWindow->setFrame(Rect(0, 0, 400, 400));
3029 spyWindow->setTrustedOverlay(true);
3030 spyWindow->setSpy(true);
3031
3032 sp<FakeWindowHandle> leftWindow =
3033 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3034 leftWindow->setFrame(Rect(0, 0, 200, 200));
3035
3036 sp<FakeWindowHandle> rightWindow =
3037 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3038 rightWindow->setFrame(Rect(200, 0, 400, 200));
3039
3040 mDispatcher->onWindowInfosChanged(
3041 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3042
3043 const int32_t stylusDeviceId = 1;
3044 const int32_t touchDeviceId = 2;
3045
3046 // Stylus hover on the left window
3047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3048 .deviceId(stylusDeviceId)
3049 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3050 .build());
3051 leftWindow->consumeMotionEvent(
3052 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053 spyWindow->consumeMotionEvent(
3054 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3055
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003056 // Touch down on the right window. Spy doesn't receive this touch because it already has
3057 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3059 .deviceId(touchDeviceId)
3060 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3061 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003062 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003063 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 rightWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3066
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003067 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3069 .deviceId(stylusDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->consumeMotionEvent(
3073 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003074 spyWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3079 .deviceId(touchDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3081 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003082 rightWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3084
3085 spyWindow->assertNoEvents();
3086 leftWindow->assertNoEvents();
3087 rightWindow->assertNoEvents();
3088}
3089
3090/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091 * On a single window, use two different devices: mouse and touch.
3092 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3093 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3094 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3095 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3096 * represent a new gesture.
3097 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003098TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3100 sp<FakeWindowHandle> window =
3101 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3102 window->setFrame(Rect(0, 0, 400, 400));
3103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003104 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003105
3106 const int32_t touchDeviceId = 4;
3107 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003109 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003110 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3111 .deviceId(touchDeviceId)
3112 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3113 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3116 .deviceId(touchDeviceId)
3117 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3118 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3122 .deviceId(touchDeviceId)
3123 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3124 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3125 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003126 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3127 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3128 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3129
3130 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3132 .deviceId(mouseDeviceId)
3133 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136
3137 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003138 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3140
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(
3142 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3143 .deviceId(mouseDeviceId)
3144 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3145 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3146 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3147 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003148 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3149
3150 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003151 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3152 .deviceId(touchDeviceId)
3153 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3154 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3155 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003156 // Since we already canceled this touch gesture, it will be ignored until a completely new
3157 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3158 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3159 // However, mouse movements should continue to work.
3160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3161 .deviceId(mouseDeviceId)
3162 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3163 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3164 .build());
3165 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3166
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003167 window->assertNoEvents();
3168}
3169
3170/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003171 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3172 * the injected event.
3173 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003174TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3176 sp<FakeWindowHandle> window =
3177 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3178 window->setFrame(Rect(0, 0, 400, 400));
3179
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003181
3182 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003183 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3184 // completion.
3185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003186 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003187 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3188 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003190 .build()));
3191 window->consumeMotionEvent(
3192 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3193
3194 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3195 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3197 .deviceId(touchDeviceId)
3198 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3199 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003200
3201 window->consumeMotionEvent(
3202 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3203 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3204}
3205
3206/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003207 * This test is similar to the test above, but the sequence of injected events is different.
3208 *
3209 * Two windows: a window on the left and a window on the right.
3210 * Mouse is hovered over the left window.
3211 * Next, we tap on the left window, where the cursor was last seen.
3212 *
3213 * After that, we inject one finger down onto the right window, and then a second finger down onto
3214 * the left window.
3215 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3216 * window (first), and then another on the left window (second).
3217 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3218 * In the buggy implementation, second finger down on the left window would cause a crash.
3219 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003220TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3222 sp<FakeWindowHandle> leftWindow =
3223 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3224 leftWindow->setFrame(Rect(0, 0, 200, 200));
3225
3226 sp<FakeWindowHandle> rightWindow =
3227 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3228 rightWindow->setFrame(Rect(200, 0, 400, 200));
3229
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003230 mDispatcher->onWindowInfosChanged(
3231 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003232
3233 const int32_t mouseDeviceId = 6;
3234 const int32_t touchDeviceId = 4;
3235 // Hover over the left window. Keep the cursor there.
3236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003237 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003238 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3239 AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003241 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003242 .build()));
3243 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3244
3245 // Tap on left window
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253
3254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003255 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003256 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3257 AINPUT_SOURCE_TOUCHSCREEN)
3258 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003260 .build()));
3261 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3262 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3263 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3264
3265 // First finger down on right window
3266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003267 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3269 AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003272 .build()));
3273 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3274
3275 // Second finger down on the left window
3276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003277 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003278 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3279 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003280 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3281 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003282 .build()));
3283 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3284 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3285
3286 // No more events
3287 leftWindow->assertNoEvents();
3288 rightWindow->assertNoEvents();
3289}
3290
3291/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003292 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3293 * While the touch is down, new hover events from the stylus device should be ignored. After the
3294 * touch is gone, stylus hovering should start working again.
3295 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003296TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3298 sp<FakeWindowHandle> window =
3299 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3300 window->setFrame(Rect(0, 0, 200, 200));
3301
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003302 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003303
3304 const int32_t stylusDeviceId = 5;
3305 const int32_t touchDeviceId = 4;
3306 // Start hovering with stylus
3307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003309 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003310 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003311 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003313 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003314
3315 // Finger down on the window
3316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003317 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003318 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003320 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003321 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003322 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003324 // Continue hovering with stylus.
3325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003326 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003327 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3328 AINPUT_SOURCE_STYLUS)
3329 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003330 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003332 // Hovers continue to work
3333 window->consumeMotionEvent(
3334 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335
3336 // Lift up the finger
3337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3340 AINPUT_SOURCE_TOUCHSCREEN)
3341 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003342 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003344
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003346 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003347 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3348 AINPUT_SOURCE_STYLUS)
3349 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003351 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003352 window->consumeMotionEvent(
3353 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003354 window->assertNoEvents();
3355}
3356
3357/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003358 * A spy window above a window with no input channel.
3359 * Start hovering with a stylus device, and then tap with it.
3360 * Ensure spy window receives the entire sequence.
3361 */
3362TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3364 sp<FakeWindowHandle> spyWindow =
3365 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3366 spyWindow->setFrame(Rect(0, 0, 200, 200));
3367 spyWindow->setTrustedOverlay(true);
3368 spyWindow->setSpy(true);
3369 sp<FakeWindowHandle> window =
3370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3371 window->setNoInputChannel(true);
3372 window->setFrame(Rect(0, 0, 200, 200));
3373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003374 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003375
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003376 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3378 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3379 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003380 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3381 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3384 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003385 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3386
3387 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3390 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003391 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3392
3393 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3396 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003397 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3398
3399 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003403 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3404 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3406 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3407 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003408 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3409
3410 // No more events
3411 spyWindow->assertNoEvents();
3412 window->assertNoEvents();
3413}
3414
3415/**
3416 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3417 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3418 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3419 * While the mouse is down, new move events from the touch device should be ignored.
3420 */
3421TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3422 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3423 sp<FakeWindowHandle> spyWindow =
3424 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3425 spyWindow->setFrame(Rect(0, 0, 200, 200));
3426 spyWindow->setTrustedOverlay(true);
3427 spyWindow->setSpy(true);
3428 sp<FakeWindowHandle> window =
3429 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3430 window->setFrame(Rect(0, 0, 200, 200));
3431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003432 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003433
3434 const int32_t mouseDeviceId = 7;
3435 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003436
3437 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3439 .deviceId(mouseDeviceId)
3440 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3441 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003442 spyWindow->consumeMotionEvent(
3443 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3444 window->consumeMotionEvent(
3445 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3446
3447 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003448 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3449 .deviceId(touchDeviceId)
3450 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3451 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003452 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3453 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3454 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3455 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3456
Prabir Pradhan678438e2023-04-13 19:32:51 +00003457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3458 .deviceId(touchDeviceId)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3460 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003461 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3462 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3463
3464 // Pilfer the stream
3465 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3466 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3467
Prabir Pradhan678438e2023-04-13 19:32:51 +00003468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3469 .deviceId(touchDeviceId)
3470 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3471 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003472 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3473
3474 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3476 .deviceId(mouseDeviceId)
3477 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3479 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003480
3481 spyWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3483 spyWindow->consumeMotionEvent(
3484 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3486
Prabir Pradhan678438e2023-04-13 19:32:51 +00003487 mDispatcher->notifyMotion(
3488 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3489 .deviceId(mouseDeviceId)
3490 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3491 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003494 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3495 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3496
3497 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3499 .deviceId(mouseDeviceId)
3500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3501 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3502 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003503 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3504 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3505
3506 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3508 .deviceId(touchDeviceId)
3509 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3510 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511
3512 // No more events
3513 spyWindow->assertNoEvents();
3514 window->assertNoEvents();
3515}
3516
3517/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003518 * On the display, have a single window, and also an area where there's no window.
3519 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3520 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3521 */
3522TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3524 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003525 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003526
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003528
3529 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003530 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003531
3532 mDispatcher->waitForIdle();
3533 window->assertNoEvents();
3534
3535 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003537 mDispatcher->waitForIdle();
3538 window->consumeMotionDown();
3539}
3540
3541/**
3542 * Same test as above, but instead of touching the empty space, the first touch goes to
3543 * non-touchable window.
3544 */
3545TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3547 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003548 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003549 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3550 window1->setTouchable(false);
3551 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003552 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003553 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3554
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003555 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003556
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003557 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003558 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003559
3560 mDispatcher->waitForIdle();
3561 window1->assertNoEvents();
3562 window2->assertNoEvents();
3563
3564 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003565 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003566 mDispatcher->waitForIdle();
3567 window2->consumeMotionDown();
3568}
3569
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003570/**
3571 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3572 * to the event time of the first ACTION_DOWN sent to the particular window.
3573 */
3574TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3576 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003577 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003578 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3579 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003581 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3582
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003583 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003584
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003585 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003586 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003587
3588 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003589
3590 MotionEvent* motionEvent1 = window1->consumeMotion();
3591 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003592 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003593 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3594 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003595
3596 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003597 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003598 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003599 MotionEvent* motionEvent2 = window2->consumeMotion();
3600 ASSERT_NE(motionEvent2, nullptr);
3601 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003603 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003604
3605 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003606 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003607 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003608 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003609
3610 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003611 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003612 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003613 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003614
3615 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3616 window1->consumeMotionMove();
3617 window1->assertNoEvents();
3618
3619 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003620 mDispatcher->notifyMotion(
3621 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003623 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003624
Prabir Pradhan678438e2023-04-13 19:32:51 +00003625 mDispatcher->notifyMotion(
3626 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003627 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003628 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003629}
3630
Garfield Tandf26e862020-07-01 20:18:19 -07003631TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003633 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003634 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003635 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003636 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003637 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003638 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003639
3640 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3641
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003642 mDispatcher->onWindowInfosChanged(
3643 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003644
3645 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003647 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003648 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3649 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003650 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003651 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003652 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003653
3654 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003656 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003657 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3658 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003659 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003660 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003661 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3662 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003663
3664 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003666 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003667 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3668 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003669 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003670 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003671 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3672 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003673
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003675 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003676 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3677 AINPUT_SOURCE_MOUSE)
3678 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3679 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003680 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003681 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003682 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003683
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003685 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003686 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3687 AINPUT_SOURCE_MOUSE)
3688 .buttonState(0)
3689 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003690 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003691 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003692 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003693
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003695 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003696 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3697 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003698 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003699 .build()));
3700 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3701
3702 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003704 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003705 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3706 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003707 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003708 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003709 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003710
3711 // No more events
3712 windowLeft->assertNoEvents();
3713 windowRight->assertNoEvents();
3714}
3715
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003716/**
3717 * Put two fingers down (and don't release them) and click the mouse button.
3718 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3719 * currently active gesture should be canceled, and the new one should proceed.
3720 */
3721TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3723 sp<FakeWindowHandle> window =
3724 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3725 window->setFrame(Rect(0, 0, 600, 800));
3726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003728
3729 const int32_t touchDeviceId = 4;
3730 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003731
3732 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3734 .deviceId(touchDeviceId)
3735 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3736 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003737
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3739 .deviceId(touchDeviceId)
3740 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3741 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3742 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003743 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3744 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3745
3746 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3748 .deviceId(mouseDeviceId)
3749 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3750 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003752 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3753 WithPointerCount(2u)));
3754 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3755
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 mDispatcher->notifyMotion(
3757 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3758 .deviceId(mouseDeviceId)
3759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3760 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3761 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3762 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003763 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3764
3765 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3766 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3768 .deviceId(touchDeviceId)
3769 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3770 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3771 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003772 window->assertNoEvents();
3773}
3774
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003775TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3777
3778 sp<FakeWindowHandle> spyWindow =
3779 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3780 spyWindow->setFrame(Rect(0, 0, 600, 800));
3781 spyWindow->setTrustedOverlay(true);
3782 spyWindow->setSpy(true);
3783 sp<FakeWindowHandle> window =
3784 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3785 window->setFrame(Rect(0, 0, 600, 800));
3786
3787 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003788 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003789
3790 // Send mouse cursor to the window
3791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003792 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003796 .build()));
3797
3798 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3799 WithSource(AINPUT_SOURCE_MOUSE)));
3800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3801 WithSource(AINPUT_SOURCE_MOUSE)));
3802
3803 window->assertNoEvents();
3804 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003805}
3806
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003807TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3809
3810 sp<FakeWindowHandle> spyWindow =
3811 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3812 spyWindow->setFrame(Rect(0, 0, 600, 800));
3813 spyWindow->setTrustedOverlay(true);
3814 spyWindow->setSpy(true);
3815 sp<FakeWindowHandle> window =
3816 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3817 window->setFrame(Rect(0, 0, 600, 800));
3818
3819 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003820 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003821
3822 // Send mouse cursor to the window
3823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003824 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003825 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3826 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003828 .build()));
3829
3830 // Move mouse cursor
3831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003832 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003833 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3834 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003836 .build()));
3837
3838 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3839 WithSource(AINPUT_SOURCE_MOUSE)));
3840 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3841 WithSource(AINPUT_SOURCE_MOUSE)));
3842 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3843 WithSource(AINPUT_SOURCE_MOUSE)));
3844 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3845 WithSource(AINPUT_SOURCE_MOUSE)));
3846 // Touch down on the window
3847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003848 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003849 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3850 AINPUT_SOURCE_TOUCHSCREEN)
3851 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003852 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003853 .build()));
3854 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3855 WithSource(AINPUT_SOURCE_MOUSE)));
3856 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3857 WithSource(AINPUT_SOURCE_MOUSE)));
3858 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3859 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3860 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3861 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3862
3863 // pilfer the motion, retaining the gesture on the spy window.
3864 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3865 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3866 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3867
3868 // Touch UP on the window
3869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003870 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003871 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3872 AINPUT_SOURCE_TOUCHSCREEN)
3873 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003874 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003875 .build()));
3876 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3877 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3878
3879 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3880 // to send a new gesture. It should again go to both windows (spy and the window below), just
3881 // like the first gesture did, before pilfering. The window configuration has not changed.
3882
3883 // One more tap - DOWN
3884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003885 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003886 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3887 AINPUT_SOURCE_TOUCHSCREEN)
3888 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003889 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003890 .build()));
3891 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3892 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3893 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3894 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3895
3896 // Touch UP on the window
3897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003898 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003899 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3900 AINPUT_SOURCE_TOUCHSCREEN)
3901 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003902 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003903 .build()));
3904 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3905 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3906 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3907 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3908
3909 window->assertNoEvents();
3910 spyWindow->assertNoEvents();
3911}
3912
Garfield Tandf26e862020-07-01 20:18:19 -07003913// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3914// directly in this test.
3915TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003917 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003918 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003919 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003920
3921 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3922
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003923 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003924
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003926 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003927 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3928 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003929 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003930 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003931 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003932 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003934 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003935 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3936 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003937 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003938 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003939 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3940 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003941
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003943 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003944 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3945 AINPUT_SOURCE_MOUSE)
3946 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3947 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003949 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003950 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003951
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003953 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003954 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3955 AINPUT_SOURCE_MOUSE)
3956 .buttonState(0)
3957 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003958 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003959 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003960 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003961
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003963 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003964 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3965 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003967 .build()));
3968 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3969
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003970 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3971 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3972 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003973 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003974 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3975 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003976 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003977 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003978 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003979}
3980
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003981/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003982 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3983 * is generated.
3984 */
3985TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3987 sp<FakeWindowHandle> window =
3988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3989 window->setFrame(Rect(0, 0, 1200, 800));
3990
3991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3992
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003993 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003994
3995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004000 .build()));
4001 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4002
4003 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004004 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004005 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4006}
4007
4008/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004009 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4010 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004011TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4012 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4013 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4015 sp<FakeWindowHandle> window =
4016 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4017 window->setFrame(Rect(0, 0, 1200, 800));
4018
4019 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4020
4021 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4022
4023 MotionEventBuilder hoverEnterBuilder =
4024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4026 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4028 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4030 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4031 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4032 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4033}
4034
4035/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004036 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4037 */
4038TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4039 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4040 sp<FakeWindowHandle> window =
4041 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4042 window->setFrame(Rect(0, 0, 100, 100));
4043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004044 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004045
4046 const int32_t mouseDeviceId = 7;
4047 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004048
4049 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4051 .deviceId(mouseDeviceId)
4052 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4053 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004054 window->consumeMotionEvent(
4055 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4056
4057 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4059 .deviceId(touchDeviceId)
4060 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4061 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004062
4063 window->consumeMotionEvent(
4064 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4065 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4066}
4067
4068/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004069 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004070 * The tap causes a HOVER_EXIT event to be generated because the current event
4071 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004072 */
4073TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4075 sp<FakeWindowHandle> window =
4076 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4077 window->setFrame(Rect(0, 0, 100, 100));
4078
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4081 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4082 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004083 ASSERT_NO_FATAL_FAILURE(
4084 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4085 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004086
4087 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4089 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4090 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004091 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004092 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4093 WithSource(AINPUT_SOURCE_MOUSE))));
4094
4095 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004096 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4097 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4098
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4100 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4101 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004102 ASSERT_NO_FATAL_FAILURE(
4103 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4104 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4105}
4106
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004107TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4109 sp<FakeWindowHandle> windowDefaultDisplay =
4110 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4111 ADISPLAY_ID_DEFAULT);
4112 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4113 sp<FakeWindowHandle> windowSecondDisplay =
4114 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4115 SECOND_DISPLAY_ID);
4116 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004118 mDispatcher->onWindowInfosChanged(
4119 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004120
4121 // Set cursor position in window in default display and check that hover enter and move
4122 // events are generated.
4123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004124 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004125 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4126 AINPUT_SOURCE_MOUSE)
4127 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004128 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004129 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004130 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004131
4132 // Remove all windows in secondary display and check that no event happens on window in
4133 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004134 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4135
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004136 windowDefaultDisplay->assertNoEvents();
4137
4138 // Move cursor position in window in default display and check that only hover move
4139 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004140 mDispatcher->onWindowInfosChanged(
4141 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004144 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4145 AINPUT_SOURCE_MOUSE)
4146 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004148 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004149 windowDefaultDisplay->consumeMotionEvent(
4150 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4151 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004152 windowDefaultDisplay->assertNoEvents();
4153}
4154
Garfield Tan00f511d2019-06-12 16:55:40 -07004155TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004157
4158 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004160 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004161 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004162 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004163 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004164
4165 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4166
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004167 mDispatcher->onWindowInfosChanged(
4168 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004169
4170 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4171 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004173 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004174 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004175 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004176 windowRight->assertNoEvents();
4177}
4178
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004179TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004181 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4182 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004183 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004184
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004185 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004186 setFocusedWindow(window);
4187
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004188 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004189
Prabir Pradhan678438e2023-04-13 19:32:51 +00004190 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004191
4192 // Window should receive key down event.
4193 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4194
4195 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4196 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004197 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004198 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004199 AKEY_EVENT_FLAG_CANCELED);
4200}
4201
4202TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004204 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4205 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004206
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004207 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004208
Prabir Pradhan678438e2023-04-13 19:32:51 +00004209 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4210 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004211
4212 // Window should receive motion down event.
4213 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4214
4215 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4216 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004217 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004218 window->consumeMotionEvent(
4219 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004220}
4221
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004222TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4224 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4225 "Fake Window", ADISPLAY_ID_DEFAULT);
4226
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004228
4229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4230 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4231 .build());
4232
4233 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4234
4235 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4236 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4238
4239 // After the device has been reset, a new hovering stream can be sent to the window
4240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4241 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4242 .build());
4243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4244}
4245
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004246TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4247 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004248 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4249 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004250 window->setFocusable(true);
4251
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004252 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004253 setFocusedWindow(window);
4254
4255 window->consumeFocusEvent(true);
4256
Prabir Pradhan678438e2023-04-13 19:32:51 +00004257 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004258 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4259 const nsecs_t injectTime = keyArgs.eventTime;
4260 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004261 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004262 // The dispatching time should be always greater than or equal to intercept key timeout.
4263 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4264 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4265 std::chrono::nanoseconds(interceptKeyTimeout).count());
4266}
4267
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004268/**
4269 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4270 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004273 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4274 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004275 window->setFocusable(true);
4276
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004277 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004278 setFocusedWindow(window);
4279
4280 window->consumeFocusEvent(true);
4281
Prabir Pradhan678438e2023-04-13 19:32:51 +00004282 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004283 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004284
4285 // Set a value that's significantly larger than the default consumption timeout. If the
4286 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4287 mFakePolicy->setInterceptKeyTimeout(600ms);
4288 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4289 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004290 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4291}
4292
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004293/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004294 * Two windows. First is a regular window. Second does not overlap with the first, and has
4295 * WATCH_OUTSIDE_TOUCH.
4296 * Both windows are owned by the same UID.
4297 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4298 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4299 */
4300TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004302 sp<FakeWindowHandle> window =
4303 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004304 window->setFrame(Rect{0, 0, 100, 100});
4305
4306 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004307 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004308 ADISPLAY_ID_DEFAULT);
4309 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4310 outsideWindow->setWatchOutsideTouch(true);
4311 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004312 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004313
4314 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004315 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4316 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4317 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004318 window->consumeMotionDown();
4319 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4320 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4321 outsideWindow->consumeMotionEvent(
4322 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4323}
4324
4325/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004326 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4327 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4328 * ACTION_OUTSIDE event is sent per gesture.
4329 */
4330TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4331 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004333 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4334 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004335 window->setWatchOutsideTouch(true);
4336 window->setFrame(Rect{0, 0, 100, 100});
4337 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004338 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4339 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004340 secondWindow->setFrame(Rect{100, 100, 200, 200});
4341 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004342 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4343 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004344 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004345 mDispatcher->onWindowInfosChanged(
4346 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004347
4348 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4350 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4351 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004352 window->assertNoEvents();
4353 secondWindow->assertNoEvents();
4354
4355 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4356 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004357 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4358 ADISPLAY_ID_DEFAULT,
4359 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004360 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4361 window->consumeMotionEvent(
4362 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004363 secondWindow->consumeMotionDown();
4364 thirdWindow->assertNoEvents();
4365
4366 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4367 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004368 mDispatcher->notifyMotion(
4369 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4370 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004371 window->assertNoEvents();
4372 secondWindow->consumeMotionMove();
4373 thirdWindow->consumeMotionDown();
4374}
4375
Prabir Pradhan814fe082022-07-22 20:22:18 +00004376TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4377 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004378 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4379 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004380 window->setFocusable(true);
4381
Patrick Williamsd828f302023-04-28 17:52:08 -05004382 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004383 setFocusedWindow(window);
4384
4385 window->consumeFocusEvent(true);
4386
Prabir Pradhan678438e2023-04-13 19:32:51 +00004387 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4388 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4389 mDispatcher->notifyKey(keyDown);
4390 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004391
4392 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4393 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4394
4395 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004396 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004397
4398 window->consumeFocusEvent(false);
4399
Prabir Pradhan678438e2023-04-13 19:32:51 +00004400 mDispatcher->notifyKey(keyDown);
4401 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004402 window->assertNoEvents();
4403}
4404
Arthur Hung96483742022-11-15 03:30:48 +00004405TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4407 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4408 "Fake Window", ADISPLAY_ID_DEFAULT);
4409 // Ensure window is non-split and have some transform.
4410 window->setPreventSplitting(true);
4411 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004413
4414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004416 {50, 50}))
4417 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4418 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4419
4420 const MotionEvent secondFingerDownEvent =
4421 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4422 .displayId(ADISPLAY_ID_DEFAULT)
4423 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004424 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4425 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004426 .build();
4427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004428 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004429 InputEventInjectionSync::WAIT_FOR_RESULT))
4430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4431
4432 const MotionEvent* event = window->consumeMotion();
4433 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4434 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4435 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4436 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4437 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4438}
4439
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004440/**
4441 * Two windows: a splittable and a non-splittable.
4442 * The non-splittable window shouldn't receive any "incomplete" gestures.
4443 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4444 * The second pointer should be dropped because the initial window is splittable, so it won't get
4445 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4446 * "incomplete" gestures.
4447 */
4448TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4450 sp<FakeWindowHandle> leftWindow =
4451 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4452 ADISPLAY_ID_DEFAULT);
4453 leftWindow->setPreventSplitting(false);
4454 leftWindow->setFrame(Rect(0, 0, 100, 100));
4455 sp<FakeWindowHandle> rightWindow =
4456 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4457 ADISPLAY_ID_DEFAULT);
4458 rightWindow->setPreventSplitting(true);
4459 rightWindow->setFrame(Rect(100, 100, 200, 200));
4460 mDispatcher->onWindowInfosChanged(
4461 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4462
4463 // Touch down on left, splittable window
4464 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4465 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4466 .build());
4467 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4468
4469 mDispatcher->notifyMotion(
4470 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4471 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4472 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4473 .build());
4474 leftWindow->assertNoEvents();
4475 rightWindow->assertNoEvents();
4476}
4477
Harry Cuttsb166c002023-05-09 13:06:05 +00004478TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4479 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4480 sp<FakeWindowHandle> window =
4481 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4482 window->setFrame(Rect(0, 0, 400, 400));
4483 sp<FakeWindowHandle> trustedOverlay =
4484 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4485 ADISPLAY_ID_DEFAULT);
4486 trustedOverlay->setSpy(true);
4487 trustedOverlay->setTrustedOverlay(true);
4488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004489 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004490
4491 // Start a three-finger touchpad swipe
4492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4493 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4494 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4495 .build());
4496 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4497 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4498 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4499 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4500 .build());
4501 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4502 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4503 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4504 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4505 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4506 .build());
4507
4508 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4509 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4510 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4511
4512 // Move the swipe a bit
4513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4514 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4515 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4516 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4517 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4518 .build());
4519
4520 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4521
4522 // End the swipe
4523 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4524 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4525 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4526 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4527 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4528 .build());
4529 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4530 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4531 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4532 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4533 .build());
4534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4535 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4536 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4537 .build());
4538
4539 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4540 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4541 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4542
4543 window->assertNoEvents();
4544}
4545
4546TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4548 sp<FakeWindowHandle> window =
4549 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4550 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004551 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004552
4553 // Start a three-finger touchpad swipe
4554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4555 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4556 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4557 .build());
4558 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4559 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4560 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4561 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4562 .build());
4563 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4564 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4565 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4566 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4567 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4568 .build());
4569
4570 // Move the swipe a bit
4571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4572 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4573 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4574 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4575 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4576 .build());
4577
4578 // End the swipe
4579 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4580 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4581 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4582 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4583 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4584 .build());
4585 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4586 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4587 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4588 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4589 .build());
4590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4591 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4592 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4593 .build());
4594
4595 window->assertNoEvents();
4596}
4597
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004598/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004599 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4600 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004601 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004602 */
4603TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4605 sp<FakeWindowHandle> window =
4606 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4607 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004608 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004609
4610 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4612 .downTime(baseTime + 10)
4613 .eventTime(baseTime + 10)
4614 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4615 .build());
4616
4617 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4618
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004619 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004620 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004621
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004622 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004623
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004624 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4625 .downTime(baseTime + 10)
4626 .eventTime(baseTime + 30)
4627 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4628 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4629 .build());
4630
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004631 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4632
4633 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004634 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4635 .downTime(baseTime + 10)
4636 .eventTime(baseTime + 40)
4637 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4638 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4639 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004640
4641 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4642
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4644 .downTime(baseTime + 10)
4645 .eventTime(baseTime + 50)
4646 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4647 .build());
4648
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004649 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4650
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4652 .downTime(baseTime + 60)
4653 .eventTime(baseTime + 60)
4654 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4655 .build());
4656
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004657 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004658}
4659
4660/**
Hu Guo771a7692023-09-17 20:51:08 +08004661 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4662 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4663 * its coordinates should be converted by the transform of the windows of target screen.
4664 */
4665TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4666 // This case will create a window and a spy window on the default display and mirror
4667 // window on the second display. cancel event is sent through spy window pilferPointers
4668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4669
4670 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4671 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4672 spyWindowDefaultDisplay->setTrustedOverlay(true);
4673 spyWindowDefaultDisplay->setSpy(true);
4674
4675 sp<FakeWindowHandle> windowDefaultDisplay =
4676 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4677 ADISPLAY_ID_DEFAULT);
4678 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4679
4680 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4681 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4682
4683 // Add the windows to the dispatcher
4684 mDispatcher->onWindowInfosChanged(
4685 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4686 *windowSecondDisplay->getInfo()},
4687 {},
4688 0,
4689 0});
4690
4691 // Send down to ADISPLAY_ID_DEFAULT
4692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4694 {100, 100}))
4695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4696
4697 spyWindowDefaultDisplay->consumeMotionDown();
4698 windowDefaultDisplay->consumeMotionDown();
4699
4700 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4701
4702 // windowDefaultDisplay gets cancel
4703 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4704 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4705
4706 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4707 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4708 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4709 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4710 EXPECT_EQ(100, event->getX(0));
4711 EXPECT_EQ(100, event->getY(0));
4712}
4713
4714/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004715 * Ensure the correct coordinate spaces are used by InputDispatcher.
4716 *
4717 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4718 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4719 * space.
4720 */
4721class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4722public:
4723 void SetUp() override {
4724 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004725 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004726 }
4727
4728 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4729 gui::DisplayInfo info;
4730 info.displayId = displayId;
4731 info.transform = transform;
4732 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004733 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004734 }
4735
4736 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4737 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004738 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004739 }
4740
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004741 void removeAllWindowsAndDisplays() {
4742 mDisplayInfos.clear();
4743 mWindowInfos.clear();
4744 }
4745
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004746 // Set up a test scenario where the display has a scaled projection and there are two windows
4747 // on the display.
4748 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4749 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4750 // respectively.
4751 ui::Transform displayTransform;
4752 displayTransform.set(2, 0, 0, 4);
4753 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4754
4755 std::shared_ptr<FakeApplicationHandle> application =
4756 std::make_shared<FakeApplicationHandle>();
4757
4758 // Add two windows to the display. Their frames are represented in the display space.
4759 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004760 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4761 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004762 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4763 addWindow(firstWindow);
4764
4765 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004766 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4767 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004768 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4769 addWindow(secondWindow);
4770 return {std::move(firstWindow), std::move(secondWindow)};
4771 }
4772
4773private:
4774 std::vector<gui::DisplayInfo> mDisplayInfos;
4775 std::vector<gui::WindowInfo> mWindowInfos;
4776};
4777
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004778TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004779 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4780 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004781 // selected so that if the hit test was performed with the point and the bounds being in
4782 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004783 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4784 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4785 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004786
4787 firstWindow->consumeMotionDown();
4788 secondWindow->assertNoEvents();
4789}
4790
4791// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4792// the event should be treated as being in the logical display space.
4793TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4794 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4795 // Send down to the first window. The point is represented in the logical display space. The
4796 // point is selected so that if the hit test was done in logical display space, then it would
4797 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004798 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004799 PointF{75 * 2, 55 * 4});
4800
4801 firstWindow->consumeMotionDown();
4802 secondWindow->assertNoEvents();
4803}
4804
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004805// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4806// event should be treated as being in the logical display space.
4807TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4808 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4809
4810 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4811 ui::Transform injectedEventTransform;
4812 injectedEventTransform.set(matrix);
4813 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4814 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4815
4816 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4817 .displayId(ADISPLAY_ID_DEFAULT)
4818 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004819 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004820 .x(untransformedPoint.x)
4821 .y(untransformedPoint.y))
4822 .build();
4823 event.transform(matrix);
4824
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004825 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004826 InputEventInjectionSync::WAIT_FOR_RESULT);
4827
4828 firstWindow->consumeMotionDown();
4829 secondWindow->assertNoEvents();
4830}
4831
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004832TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4833 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4834
4835 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004836 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4837 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4838 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004839
4840 firstWindow->assertNoEvents();
4841 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004842 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004843 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4844
4845 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4846 EXPECT_EQ(300, event->getRawX(0));
4847 EXPECT_EQ(880, event->getRawY(0));
4848
4849 // Ensure that the x and y values are in the window's coordinate space.
4850 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4851 // the logical display space. This will be the origin of the window space.
4852 EXPECT_EQ(100, event->getX(0));
4853 EXPECT_EQ(80, event->getY(0));
4854}
4855
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004856TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4857 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4858 // The monitor will always receive events in the logical display's coordinate space, because
4859 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004860 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004861
4862 // Send down to the first window.
4863 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4864 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4865 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4866 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4867
4868 // Second pointer goes down on second window.
4869 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4870 ADISPLAY_ID_DEFAULT,
4871 {PointF{50, 100}, PointF{150, 220}}));
4872 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4873 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4874 {1, PointF{300, 880}}};
4875 monitor.consumeMotionEvent(
4876 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4877
4878 mDispatcher->cancelCurrentTouch();
4879
4880 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4881 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4882 monitor.consumeMotionEvent(
4883 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4884}
4885
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004886TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4887 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4888
4889 // Send down to the first window.
4890 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4891 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4892 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4893
4894 // The pointer is transferred to the second window, and the second window receives it in the
4895 // correct coordinate space.
4896 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4897 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4898 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4899}
4900
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004901TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4902 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4903
4904 // Send hover move to the second window, and ensure it shows up as hover enter.
4905 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4906 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4907 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4908 WithCoords(100, 80), WithRawCoords(300, 880)));
4909
4910 // Touch down at the same location and ensure a hover exit is synthesized.
4911 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4912 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4913 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4914 WithRawCoords(300, 880)));
4915 secondWindow->consumeMotionEvent(
4916 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4917 secondWindow->assertNoEvents();
4918 firstWindow->assertNoEvents();
4919}
4920
Prabir Pradhan453ae732023-10-13 14:30:14 +00004921// Same as above, but while the window is being mirrored.
4922TEST_F(InputDispatcherDisplayProjectionTest,
4923 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4924 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4925
4926 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4927 ui::Transform secondDisplayTransform;
4928 secondDisplayTransform.set(matrix);
4929 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4930
4931 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4932 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4933 addWindow(secondWindowClone);
4934
4935 // Send hover move to the second window, and ensure it shows up as hover enter.
4936 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4937 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4938 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4939 WithCoords(100, 80), WithRawCoords(300, 880)));
4940
4941 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4942 // display.
4943 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4944 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4945 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4946 WithRawCoords(300, 880)));
4947 secondWindow->consumeMotionEvent(
4948 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4949 secondWindow->assertNoEvents();
4950 firstWindow->assertNoEvents();
4951}
4952
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004953TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4954 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4955
4956 // Send hover enter to second window
4957 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4958 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4959 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4960 WithCoords(100, 80), WithRawCoords(300, 880)));
4961
4962 mDispatcher->cancelCurrentTouch();
4963
4964 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4965 WithRawCoords(300, 880)));
4966 secondWindow->assertNoEvents();
4967 firstWindow->assertNoEvents();
4968}
4969
Prabir Pradhan453ae732023-10-13 14:30:14 +00004970// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004971TEST_F(InputDispatcherDisplayProjectionTest,
4972 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4973 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4974
4975 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4976 ui::Transform secondDisplayTransform;
4977 secondDisplayTransform.set(matrix);
4978 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4979
4980 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4981 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4982 addWindow(secondWindowClone);
4983
4984 // Send hover enter to second window
4985 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4986 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4987 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4988 WithCoords(100, 80), WithRawCoords(300, 880),
4989 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4990
4991 mDispatcher->cancelCurrentTouch();
4992
4993 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4994 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4995 WithRawCoords(300, 880),
4996 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4997 secondWindow->assertNoEvents();
4998 firstWindow->assertNoEvents();
4999}
5000
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005001/** Ensure consistent behavior of InputDispatcher in all orientations. */
5002class InputDispatcherDisplayOrientationFixture
5003 : public InputDispatcherDisplayProjectionTest,
5004 public ::testing::WithParamInterface<ui::Rotation> {};
5005
5006// This test verifies the touchable region of a window for all rotations of the display by tapping
5007// in different locations on the display, specifically points close to the four corners of a
5008// window.
5009TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5010 constexpr static int32_t displayWidth = 400;
5011 constexpr static int32_t displayHeight = 800;
5012
5013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5014
5015 const auto rotation = GetParam();
5016
5017 // Set up the display with the specified rotation.
5018 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5019 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5020 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5021 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5022 logicalDisplayWidth, logicalDisplayHeight);
5023 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5024
5025 // Create a window with its bounds determined in the logical display.
5026 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5027 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5028 sp<FakeWindowHandle> window =
5029 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5030 window->setFrame(frameInDisplay, displayTransform);
5031 addWindow(window);
5032
5033 // The following points in logical display space should be inside the window.
5034 static const std::array<vec2, 4> insidePoints{
5035 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5036 for (const auto pointInsideWindow : insidePoints) {
5037 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5038 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005039 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5040 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5041 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005042 window->consumeMotionDown();
5043
Prabir Pradhan678438e2023-04-13 19:32:51 +00005044 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5045 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5046 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005047 window->consumeMotionUp();
5048 }
5049
5050 // The following points in logical display space should be outside the window.
5051 static const std::array<vec2, 5> outsidePoints{
5052 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5053 for (const auto pointOutsideWindow : outsidePoints) {
5054 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5055 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005056 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5057 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5058 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005059
Prabir Pradhan678438e2023-04-13 19:32:51 +00005060 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5061 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5062 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005063 }
5064 window->assertNoEvents();
5065}
5066
5067// Run the precision tests for all rotations.
5068INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5069 InputDispatcherDisplayOrientationFixture,
5070 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5071 ui::ROTATION_270),
5072 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5073 return ftl::enum_string(testParamInfo.param);
5074 });
5075
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005076using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5077 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005078
5079class TransferTouchFixture : public InputDispatcherTest,
5080 public ::testing::WithParamInterface<TransferFunction> {};
5081
5082TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005084
5085 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005086 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005087 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5088 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005089 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005090 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005091 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5092 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005093 sp<FakeWindowHandle> wallpaper =
5094 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5095 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005096 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005097 mDispatcher->onWindowInfosChanged(
5098 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005099
5100 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005101 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5102 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005103
Svet Ganov5d3bc372020-01-26 23:11:07 -08005104 // Only the first window should get the down event
5105 firstWindow->consumeMotionDown();
5106 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005107 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005108
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005109 // Transfer touch to the second window
5110 TransferFunction f = GetParam();
5111 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5112 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005113 // The first window gets cancel and the second gets down
5114 firstWindow->consumeMotionCancel();
5115 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005116 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005117
5118 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005119 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5120 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005121 // The first window gets no events and the second gets up
5122 firstWindow->assertNoEvents();
5123 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005124 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005125}
5126
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005127/**
5128 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5129 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5130 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5131 * natural to the user.
5132 * In this test, we are sending a pointer to both spy window and first window. We then try to
5133 * transfer touch to the second window. The dispatcher should identify the first window as the
5134 * one that should lose the gesture, and therefore the action should be to move the gesture from
5135 * the first window to the second.
5136 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5137 * the other API, as well.
5138 */
5139TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5141
5142 // Create a couple of windows + a spy window
5143 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005144 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005145 spyWindow->setTrustedOverlay(true);
5146 spyWindow->setSpy(true);
5147 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005148 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005149 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005150 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005151
5152 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005153 mDispatcher->onWindowInfosChanged(
5154 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005155
5156 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005157 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5158 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005159 // Only the first window and spy should get the down event
5160 spyWindow->consumeMotionDown();
5161 firstWindow->consumeMotionDown();
5162
5163 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5164 // if f === 'transferTouch'.
5165 TransferFunction f = GetParam();
5166 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5167 ASSERT_TRUE(success);
5168 // The first window gets cancel and the second gets down
5169 firstWindow->consumeMotionCancel();
5170 secondWindow->consumeMotionDown();
5171
5172 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005173 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5174 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005175 // The first window gets no events and the second+spy get up
5176 firstWindow->assertNoEvents();
5177 spyWindow->consumeMotionUp();
5178 secondWindow->consumeMotionUp();
5179}
5180
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005181TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005182 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005183
5184 PointF touchPoint = {10, 10};
5185
5186 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005187 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005188 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5189 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005190 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005191 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005192 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5193 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005194 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005195
5196 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005197 mDispatcher->onWindowInfosChanged(
5198 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005199
5200 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5202 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5203 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005204 // Only the first window should get the down event
5205 firstWindow->consumeMotionDown();
5206 secondWindow->assertNoEvents();
5207
5208 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005209 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5210 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005211 // Only the first window should get the pointer down event
5212 firstWindow->consumeMotionPointerDown(1);
5213 secondWindow->assertNoEvents();
5214
5215 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005216 TransferFunction f = GetParam();
5217 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5218 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005219 // The first window gets cancel and the second gets down and pointer down
5220 firstWindow->consumeMotionCancel();
5221 secondWindow->consumeMotionDown();
5222 secondWindow->consumeMotionPointerDown(1);
5223
5224 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005225 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5226 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005227 // The first window gets nothing and the second gets pointer up
5228 firstWindow->assertNoEvents();
5229 secondWindow->consumeMotionPointerUp(1);
5230
5231 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5233 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005234 // The first window gets nothing and the second gets up
5235 firstWindow->assertNoEvents();
5236 secondWindow->consumeMotionUp();
5237}
5238
Arthur Hungc539dbb2022-12-08 07:45:36 +00005239TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5241
5242 // Create a couple of windows
5243 sp<FakeWindowHandle> firstWindow =
5244 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5245 ADISPLAY_ID_DEFAULT);
5246 firstWindow->setDupTouchToWallpaper(true);
5247 sp<FakeWindowHandle> secondWindow =
5248 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5249 ADISPLAY_ID_DEFAULT);
5250 secondWindow->setDupTouchToWallpaper(true);
5251
5252 sp<FakeWindowHandle> wallpaper1 =
5253 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5254 wallpaper1->setIsWallpaper(true);
5255
5256 sp<FakeWindowHandle> wallpaper2 =
5257 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5258 wallpaper2->setIsWallpaper(true);
5259 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005260 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5261 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5262 {},
5263 0,
5264 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005265
5266 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005267 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5268 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005269
5270 // Only the first window should get the down event
5271 firstWindow->consumeMotionDown();
5272 secondWindow->assertNoEvents();
5273 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5274 wallpaper2->assertNoEvents();
5275
5276 // Transfer touch focus to the second window
5277 TransferFunction f = GetParam();
5278 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5279 ASSERT_TRUE(success);
5280
5281 // The first window gets cancel and the second gets down
5282 firstWindow->consumeMotionCancel();
5283 secondWindow->consumeMotionDown();
5284 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5285 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5286
5287 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005288 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5289 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005290 // The first window gets no events and the second gets up
5291 firstWindow->assertNoEvents();
5292 secondWindow->consumeMotionUp();
5293 wallpaper1->assertNoEvents();
5294 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5295}
5296
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005297// For the cases of single pointer touch and two pointers non-split touch, the api's
5298// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5299// for the case where there are multiple pointers split across several windows.
5300INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5301 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005302 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5303 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005304 return dispatcher->transferTouch(destChannelToken,
5305 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005306 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005307 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5308 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005309 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005310 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005311 }));
5312
Svet Ganov5d3bc372020-01-26 23:11:07 -08005313TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005315
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005316 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005317 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5318 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005319 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005320
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005321 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005322 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5323 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005324 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005325
5326 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005327 mDispatcher->onWindowInfosChanged(
5328 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005329
5330 PointF pointInFirst = {300, 200};
5331 PointF pointInSecond = {300, 600};
5332
5333 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005334 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5335 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5336 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005337 // Only the first window should get the down event
5338 firstWindow->consumeMotionDown();
5339 secondWindow->assertNoEvents();
5340
5341 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005342 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5343 ADISPLAY_ID_DEFAULT,
5344 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005345 // The first window gets a move and the second a down
5346 firstWindow->consumeMotionMove();
5347 secondWindow->consumeMotionDown();
5348
5349 // Transfer touch focus to the second window
5350 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5351 // The first window gets cancel and the new gets pointer down (it already saw down)
5352 firstWindow->consumeMotionCancel();
5353 secondWindow->consumeMotionPointerDown(1);
5354
5355 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005356 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5357 ADISPLAY_ID_DEFAULT,
5358 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359 // The first window gets nothing and the second gets pointer up
5360 firstWindow->assertNoEvents();
5361 secondWindow->consumeMotionPointerUp(1);
5362
5363 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005364 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5365 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005366 // The first window gets nothing and the second gets up
5367 firstWindow->assertNoEvents();
5368 secondWindow->consumeMotionUp();
5369}
5370
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005371// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5372// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5373// touch is not supported, so the touch should continue on those windows and the transferred-to
5374// window should get nothing.
5375TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5377
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005378 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005379 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5380 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005381 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005382
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005383 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005384 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5385 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005386 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005387
5388 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005389 mDispatcher->onWindowInfosChanged(
5390 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005391
5392 PointF pointInFirst = {300, 200};
5393 PointF pointInSecond = {300, 600};
5394
5395 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5397 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5398 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005399 // Only the first window should get the down event
5400 firstWindow->consumeMotionDown();
5401 secondWindow->assertNoEvents();
5402
5403 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005404 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5405 ADISPLAY_ID_DEFAULT,
5406 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005407 // The first window gets a move and the second a down
5408 firstWindow->consumeMotionMove();
5409 secondWindow->consumeMotionDown();
5410
5411 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005412 const bool transferred =
5413 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005414 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5415 ASSERT_FALSE(transferred);
5416 firstWindow->assertNoEvents();
5417 secondWindow->assertNoEvents();
5418
5419 // The rest of the dispatch should proceed as normal
5420 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005421 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5422 ADISPLAY_ID_DEFAULT,
5423 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005424 // The first window gets MOVE and the second gets pointer up
5425 firstWindow->consumeMotionMove();
5426 secondWindow->consumeMotionUp();
5427
5428 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005429 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5430 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005431 // The first window gets nothing and the second gets up
5432 firstWindow->consumeMotionUp();
5433 secondWindow->assertNoEvents();
5434}
5435
Arthur Hungabbb9d82021-09-01 14:52:30 +00005436// This case will create two windows and one mirrored window on the default display and mirror
5437// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5438// the windows info of second display before default display.
5439TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5441 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005442 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005443 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005444 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005445 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005446 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005447
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005448 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005449 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005450
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005451 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005452 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005453
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005454 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005455 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005456
5457 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005458 mDispatcher->onWindowInfosChanged(
5459 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5460 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5461 *secondWindowInPrimary->getInfo()},
5462 {},
5463 0,
5464 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005465
5466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005468 {50, 50}))
5469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5470
5471 // Window should receive motion event.
5472 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5473
5474 // Transfer touch focus
5475 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5476 secondWindowInPrimary->getToken()));
5477 // The first window gets cancel.
5478 firstWindowInPrimary->consumeMotionCancel();
5479 secondWindowInPrimary->consumeMotionDown();
5480
5481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005482 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005483 ADISPLAY_ID_DEFAULT, {150, 50}))
5484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5485 firstWindowInPrimary->assertNoEvents();
5486 secondWindowInPrimary->consumeMotionMove();
5487
5488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005489 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005490 {150, 50}))
5491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5492 firstWindowInPrimary->assertNoEvents();
5493 secondWindowInPrimary->consumeMotionUp();
5494}
5495
5496// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5497// 'transferTouch' api.
5498TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5500 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005501 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005502 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005503 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005504 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005505 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005506
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005507 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005508 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005509
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005510 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005511 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005513 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005514 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005515
5516 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005517 mDispatcher->onWindowInfosChanged(
5518 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5519 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5520 *secondWindowInPrimary->getInfo()},
5521 {},
5522 0,
5523 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005524
5525 // Touch on second display.
5526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005527 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5528 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5530
5531 // Window should receive motion event.
5532 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5533
5534 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005535 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005536
5537 // The first window gets cancel.
5538 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5539 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5540
5541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005542 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005543 SECOND_DISPLAY_ID, {150, 50}))
5544 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5545 firstWindowInPrimary->assertNoEvents();
5546 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5547
5548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005549 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5551 firstWindowInPrimary->assertNoEvents();
5552 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5553}
5554
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005555TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005557 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5558 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005559
Vishnu Nair47074b82020-08-14 11:54:47 -07005560 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005561 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005562 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005563
5564 window->consumeFocusEvent(true);
5565
Prabir Pradhan678438e2023-04-13 19:32:51 +00005566 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005567
5568 // Window should receive key down event.
5569 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005570
5571 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005572 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005573 mFakePolicy->assertUserActivityPoked();
5574}
5575
5576TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5578 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5579 "Fake Window", ADISPLAY_ID_DEFAULT);
5580
5581 window->setDisableUserActivity(true);
5582 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005583 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005584 setFocusedWindow(window);
5585
5586 window->consumeFocusEvent(true);
5587
5588 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5589
5590 // Window should receive key down event.
5591 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5592
5593 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005594 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005595 mFakePolicy->assertUserActivityNotPoked();
5596}
5597
5598TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5600 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5601 "Fake Window", ADISPLAY_ID_DEFAULT);
5602
5603 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005604 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005605 setFocusedWindow(window);
5606
5607 window->consumeFocusEvent(true);
5608
5609 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5610 mDispatcher->waitForIdle();
5611
5612 // System key is not passed down
5613 window->assertNoEvents();
5614
5615 // Should have poked user activity
5616 mFakePolicy->assertUserActivityPoked();
5617}
5618
5619TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5621 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5622 "Fake Window", ADISPLAY_ID_DEFAULT);
5623
5624 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005625 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005626 setFocusedWindow(window);
5627
5628 window->consumeFocusEvent(true);
5629
5630 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5631 mDispatcher->waitForIdle();
5632
5633 // System key is not passed down
5634 window->assertNoEvents();
5635
5636 // Should have poked user activity
5637 mFakePolicy->assertUserActivityPoked();
5638}
5639
5640TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5641 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5642 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5643 "Fake Window", ADISPLAY_ID_DEFAULT);
5644
5645 window->setDisableUserActivity(true);
5646 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005647 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005648 setFocusedWindow(window);
5649
5650 window->consumeFocusEvent(true);
5651
5652 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5653 mDispatcher->waitForIdle();
5654
5655 // System key is not passed down
5656 window->assertNoEvents();
5657
5658 // Should have poked user activity
5659 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005660}
5661
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005662TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5664 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5665 "Fake Window", ADISPLAY_ID_DEFAULT);
5666
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005667 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005668
5669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005670 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005671 ADISPLAY_ID_DEFAULT, {100, 100}))
5672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5673
5674 window->consumeMotionEvent(
5675 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5676
5677 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005678 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005679 mFakePolicy->assertUserActivityPoked();
5680}
5681
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005682TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5685 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005688
Prabir Pradhan678438e2023-04-13 19:32:51 +00005689 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005690 mDispatcher->waitForIdle();
5691
5692 window->assertNoEvents();
5693}
5694
5695// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5696TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005698 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5699 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005700
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005701 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005702
5703 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005704 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005705 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005706 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5707 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005708
5709 // Window should receive only the motion event
5710 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5711 window->assertNoEvents(); // Key event or focus event will not be received
5712}
5713
arthurhungea3f4fc2020-12-21 23:18:53 +08005714TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5716
arthurhungea3f4fc2020-12-21 23:18:53 +08005717 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005718 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5719 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005720 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005721
arthurhungea3f4fc2020-12-21 23:18:53 +08005722 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005723 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5724 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005725 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005726
5727 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005728 mDispatcher->onWindowInfosChanged(
5729 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005730
5731 PointF pointInFirst = {300, 200};
5732 PointF pointInSecond = {300, 600};
5733
5734 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005735 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5736 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5737 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005738 // Only the first window should get the down event
5739 firstWindow->consumeMotionDown();
5740 secondWindow->assertNoEvents();
5741
5742 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005743 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5744 ADISPLAY_ID_DEFAULT,
5745 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005746 // The first window gets a move and the second a down
5747 firstWindow->consumeMotionMove();
5748 secondWindow->consumeMotionDown();
5749
5750 // Send pointer cancel to the second window
5751 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005752 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005753 {pointInFirst, pointInSecond});
5754 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005755 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005756 // The first window gets move and the second gets cancel.
5757 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5758 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5759
5760 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5762 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005763 // The first window gets up and the second gets nothing.
5764 firstWindow->consumeMotionUp();
5765 secondWindow->assertNoEvents();
5766}
5767
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005768TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5770
5771 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005773 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005774 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5775 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5776 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5777
Harry Cutts33476232023-01-30 19:57:29 +00005778 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005779 window->assertNoEvents();
5780 mDispatcher->waitForIdle();
5781}
5782
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005783using InputDispatcherMonitorTest = InputDispatcherTest;
5784
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005785/**
5786 * Two entities that receive touch: A window, and a global monitor.
5787 * The touch goes to the window, and then the window disappears.
5788 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5789 * for the monitor, as well.
5790 * 1. foregroundWindow
5791 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5792 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005793TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5795 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005796 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005797
Prabir Pradhanfb549072023-10-05 19:17:36 +00005798 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005799
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005802 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005803 {100, 200}))
5804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5805
5806 // Both the foreground window and the global monitor should receive the touch down
5807 window->consumeMotionDown();
5808 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5809
5810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005811 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005812 ADISPLAY_ID_DEFAULT, {110, 200}))
5813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5814
5815 window->consumeMotionMove();
5816 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5817
5818 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005819 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005820 window->consumeMotionCancel();
5821 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5822
5823 // If more events come in, there will be no more foreground window to send them to. This will
5824 // cause a cancel for the monitor, as well.
5825 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005826 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005827 ADISPLAY_ID_DEFAULT, {120, 200}))
5828 << "Injection should fail because the window was removed";
5829 window->assertNoEvents();
5830 // Global monitor now gets the cancel
5831 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5832}
5833
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005834TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005836 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5837 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005838 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005839
Prabir Pradhanfb549072023-10-05 19:17:36 +00005840 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005841
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005844 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005845 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005846 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005847}
5848
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005849TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005850 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005851
Chris Yea209fde2020-07-22 13:54:51 -07005852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005853 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5854 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005856
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005860 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005861 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005862
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005863 // Pilfer pointers from the monitor.
5864 // This should not do anything and the window should continue to receive events.
5865 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005866
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005868 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005869 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005871
5872 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5873 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005874}
5875
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005876TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005878 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5879 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005880 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005881 window->setWindowOffset(20, 40);
5882 window->setWindowTransform(0, 1, -1, 0);
5883
Prabir Pradhanfb549072023-10-05 19:17:36 +00005884 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005885
5886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005887 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5889 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5890 MotionEvent* event = monitor.consumeMotion();
5891 // Even though window has transform, gesture monitor must not.
5892 ASSERT_EQ(ui::Transform(), event->getTransform());
5893}
5894
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005895TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005897 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005898
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005899 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005900 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005901 << "Injection should fail if there is a monitor, but no touchable window";
5902 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005903}
5904
chaviw81e2bb92019-12-18 15:03:51 -08005905TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005907 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5908 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005909
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005910 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005911
5912 NotifyMotionArgs motionArgs =
5913 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5914 ADISPLAY_ID_DEFAULT);
5915
Prabir Pradhan678438e2023-04-13 19:32:51 +00005916 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005917 // Window should receive motion down event.
5918 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5919
5920 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005921 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005922 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5923 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5924 motionArgs.pointerCoords[0].getX() - 10);
5925
Prabir Pradhan678438e2023-04-13 19:32:51 +00005926 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005927 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005928 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005929}
5930
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005931/**
5932 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5933 * the device default right away. In the test scenario, we check both the default value,
5934 * and the action of enabling / disabling.
5935 */
5936TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5939 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005940 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005941
5942 // Set focused application.
5943 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005944 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005945
5946 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005947 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005948 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005949 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005950
5951 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005952 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005953 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005954 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005955
5956 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005957 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005958 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005959 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005960 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005961 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005962 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005963 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005964
5965 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005966 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005968 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005969
5970 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005971 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005972 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005973 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005974 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005975 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005976 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005977 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005978
5979 window->assertNoEvents();
5980}
5981
Gang Wange9087892020-01-07 12:17:14 -05005982TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005984 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5985 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005986
5987 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005988 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005990 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005991 setFocusedWindow(window);
5992
Harry Cutts33476232023-01-30 19:57:29 +00005993 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005994
Prabir Pradhan678438e2023-04-13 19:32:51 +00005995 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5996 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005997
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005998 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005999 ASSERT_NE(event, nullptr);
6000
6001 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6002 ASSERT_NE(verified, nullptr);
6003 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6004
6005 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6006 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6007 ASSERT_EQ(keyArgs.source, verified->source);
6008 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6009
6010 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6011
6012 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006013 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006014 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006015 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6016 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6017 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6018 ASSERT_EQ(0, verifiedKey.repeatCount);
6019}
6020
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006021TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006023 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6024 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006025
6026 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6027
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006028 ui::Transform transform;
6029 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6030
6031 gui::DisplayInfo displayInfo;
6032 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6033 displayInfo.transform = transform;
6034
Patrick Williamsd828f302023-04-28 17:52:08 -05006035 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006036
Prabir Pradhan678438e2023-04-13 19:32:51 +00006037 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006038 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6039 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006040 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006041
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006042 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006043 ASSERT_NE(event, nullptr);
6044
6045 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6046 ASSERT_NE(verified, nullptr);
6047 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6048
6049 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6050 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6051 EXPECT_EQ(motionArgs.source, verified->source);
6052 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6053
6054 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6055
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006056 const vec2 rawXY =
6057 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6058 motionArgs.pointerCoords[0].getXYValue());
6059 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6060 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006061 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006062 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006063 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006064 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6065 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6066}
6067
chaviw09c8d2d2020-08-24 15:48:26 -07006068/**
6069 * Ensure that separate calls to sign the same data are generating the same key.
6070 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6071 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6072 * tests.
6073 */
6074TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6075 KeyEvent event = getTestKeyEvent();
6076 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6077
6078 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6079 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6080 ASSERT_EQ(hmac1, hmac2);
6081}
6082
6083/**
6084 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6085 */
6086TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6087 KeyEvent event = getTestKeyEvent();
6088 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6089 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6090
6091 verifiedEvent.deviceId += 1;
6092 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6093
6094 verifiedEvent.source += 1;
6095 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6096
6097 verifiedEvent.eventTimeNanos += 1;
6098 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6099
6100 verifiedEvent.displayId += 1;
6101 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6102
6103 verifiedEvent.action += 1;
6104 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6105
6106 verifiedEvent.downTimeNanos += 1;
6107 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6108
6109 verifiedEvent.flags += 1;
6110 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6111
6112 verifiedEvent.keyCode += 1;
6113 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6114
6115 verifiedEvent.scanCode += 1;
6116 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6117
6118 verifiedEvent.metaState += 1;
6119 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6120
6121 verifiedEvent.repeatCount += 1;
6122 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6123}
6124
Vishnu Nair958da932020-08-21 17:12:37 -07006125TEST_F(InputDispatcherTest, SetFocusedWindow) {
6126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6127 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006128 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006129 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006130 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006131 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6132
6133 // Top window is also focusable but is not granted focus.
6134 windowTop->setFocusable(true);
6135 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006136 mDispatcher->onWindowInfosChanged(
6137 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006138 setFocusedWindow(windowSecond);
6139
6140 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006142 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006143
6144 // Focused window should receive event.
6145 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6146 windowTop->assertNoEvents();
6147}
6148
6149TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6151 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006152 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006153 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6154
6155 window->setFocusable(true);
6156 // Release channel for window is no longer valid.
6157 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006158 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006159 setFocusedWindow(window);
6160
6161 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006162 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006163
6164 // window channel is invalid, so it should not receive any input event.
6165 window->assertNoEvents();
6166}
6167
6168TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6170 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006171 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006172 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6174
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006175 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006176 setFocusedWindow(window);
6177
6178 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006179 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006180
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006181 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006182 window->assertNoEvents();
6183}
6184
6185TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6187 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006188 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006189 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006190 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6192
6193 windowTop->setFocusable(true);
6194 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006195 mDispatcher->onWindowInfosChanged(
6196 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006197 setFocusedWindow(windowTop);
6198 windowTop->consumeFocusEvent(true);
6199
Chavi Weingarten847e8512023-03-29 00:26:09 +00006200 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006201 mDispatcher->onWindowInfosChanged(
6202 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006203 windowSecond->consumeFocusEvent(true);
6204 windowTop->consumeFocusEvent(false);
6205
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006207 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006208
6209 // Focused window should receive event.
6210 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6211}
6212
Chavi Weingarten847e8512023-03-29 00:26:09 +00006213TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6215 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006216 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006217 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006218 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006219 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6220
6221 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006222 windowSecond->setFocusable(false);
6223 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006224 mDispatcher->onWindowInfosChanged(
6225 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006226 setFocusedWindow(windowTop);
6227 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006228
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006230 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006231
6232 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006233 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006234 windowSecond->assertNoEvents();
6235}
6236
6237TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6239 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006240 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006241 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006242 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6243 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006244 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6245
6246 window->setFocusable(true);
6247 previousFocusedWindow->setFocusable(true);
6248 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006249 mDispatcher->onWindowInfosChanged(
6250 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006251 setFocusedWindow(previousFocusedWindow);
6252 previousFocusedWindow->consumeFocusEvent(true);
6253
6254 // Requesting focus on invisible window takes focus from currently focused window.
6255 setFocusedWindow(window);
6256 previousFocusedWindow->consumeFocusEvent(false);
6257
6258 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006260 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6261 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006262
6263 // Window does not get focus event or key down.
6264 window->assertNoEvents();
6265
6266 // Window becomes visible.
6267 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006268 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006269
6270 // Window receives focus event.
6271 window->consumeFocusEvent(true);
6272 // Focused window receives key down.
6273 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6274}
6275
Vishnu Nair599f1412021-06-21 10:39:58 -07006276TEST_F(InputDispatcherTest, DisplayRemoved) {
6277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6278 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006279 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006280 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6281
6282 // window is granted focus.
6283 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006285 setFocusedWindow(window);
6286 window->consumeFocusEvent(true);
6287
6288 // When a display is removed window loses focus.
6289 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6290 window->consumeFocusEvent(false);
6291}
6292
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006293/**
6294 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6295 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6296 * of the 'slipperyEnterWindow'.
6297 *
6298 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6299 * a way so that the touched location is no longer covered by the top window.
6300 *
6301 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6302 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6303 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6304 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6305 * with ACTION_DOWN).
6306 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6307 * window moved itself away from the touched location and had Flag::SLIPPERY.
6308 *
6309 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6310 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6311 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6312 *
6313 * In this test, we ensure that the event received by the bottom window has
6314 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6315 */
6316TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006317 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006318 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006319
6320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6321 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6322
6323 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006324 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006325 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006326 // Make sure this one overlaps the bottom window
6327 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6328 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6329 // one. Windows with the same owner are not considered to be occluding each other.
6330 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6331
6332 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006333 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006334 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6335
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006336 mDispatcher->onWindowInfosChanged(
6337 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006338
6339 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006340 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6341 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6342 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006343 slipperyExitWindow->consumeMotionDown();
6344 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006345 mDispatcher->onWindowInfosChanged(
6346 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006347
Prabir Pradhan678438e2023-04-13 19:32:51 +00006348 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6349 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6350 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006351
6352 slipperyExitWindow->consumeMotionCancel();
6353
6354 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6355 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6356}
6357
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006358/**
6359 * Two windows, one on the left and another on the right. The left window is slippery. The right
6360 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6361 * touch moves from the left window into the right window, the gesture should continue to go to the
6362 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6363 * reproduces a crash.
6364 */
6365TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6367
6368 sp<FakeWindowHandle> leftSlipperyWindow =
6369 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6370 leftSlipperyWindow->setSlippery(true);
6371 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6372
6373 sp<FakeWindowHandle> rightDropTouchesWindow =
6374 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6375 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6376 rightDropTouchesWindow->setDropInput(true);
6377
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006378 mDispatcher->onWindowInfosChanged(
6379 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006380
6381 // Start touch in the left window
6382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6383 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6384 .build());
6385 leftSlipperyWindow->consumeMotionDown();
6386
6387 // And move it into the right window
6388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6389 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6390 .build());
6391
6392 // Since the right window isn't eligible to receive input, touch does not slip.
6393 // The left window continues to receive the gesture.
6394 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6395 rightDropTouchesWindow->assertNoEvents();
6396}
6397
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006398/**
6399 * A single window is on screen first. Touch is injected into that window. Next, a second window
6400 * appears. Since the first window is slippery, touch will move from the first window to the second.
6401 */
6402TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6404 sp<FakeWindowHandle> originalWindow =
6405 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6406 originalWindow->setFrame(Rect(0, 0, 200, 200));
6407 originalWindow->setSlippery(true);
6408
6409 sp<FakeWindowHandle> appearingWindow =
6410 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6411 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6412
6413 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6414
6415 // Touch down on the original window
6416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6417 injectMotionEvent(*mDispatcher,
6418 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6419 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6420 .build()));
6421 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6422
6423 // Now, a new window appears. This could be, for example, a notification shade that appears
6424 // after user starts to drag down on the launcher window.
6425 mDispatcher->onWindowInfosChanged(
6426 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6428 injectMotionEvent(*mDispatcher,
6429 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6430 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6431 .build()));
6432 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6433 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6435 injectMotionEvent(*mDispatcher,
6436 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6437 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6438 .build()));
6439 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6440
6441 originalWindow->assertNoEvents();
6442 appearingWindow->assertNoEvents();
6443}
6444
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006445TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006446 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6448
6449 sp<FakeWindowHandle> leftWindow =
6450 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6451 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006452 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006453
6454 sp<FakeWindowHandle> rightSpy =
6455 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6456 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006457 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006458 rightSpy->setSpy(true);
6459 rightSpy->setTrustedOverlay(true);
6460
6461 sp<FakeWindowHandle> rightWindow =
6462 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6463 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006464 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006465
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006466 mDispatcher->onWindowInfosChanged(
6467 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006468
6469 // Touch in the left window
6470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6471 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6472 .build());
6473 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6474 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006475 ASSERT_NO_FATAL_FAILURE(
6476 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006477
6478 // Touch another finger over the right windows
6479 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6480 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6481 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6482 .build());
6483 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6484 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6485 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6486 mDispatcher->waitForIdle();
6487 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006488 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6489 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006490
6491 // Release finger over left window. The UP actions are not treated as device interaction.
6492 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6493 // is part of the UP action, we do not treat this as device interaction.
6494 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6495 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6496 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6497 .build());
6498 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6499 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6500 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6501 mDispatcher->waitForIdle();
6502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6503
6504 // Move remaining finger
6505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6506 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6507 .build());
6508 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6509 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6510 mDispatcher->waitForIdle();
6511 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006512 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006513
6514 // Release all fingers
6515 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6516 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6517 .build());
6518 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6519 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6520 mDispatcher->waitForIdle();
6521 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6522}
6523
6524TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6526
6527 sp<FakeWindowHandle> window =
6528 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6529 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006530 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006531
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006533 setFocusedWindow(window);
6534 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6535
6536 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6537 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6538 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006539 ASSERT_NO_FATAL_FAILURE(
6540 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006541
6542 // The UP actions are not treated as device interaction.
6543 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6544 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6545 mDispatcher->waitForIdle();
6546 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6547}
6548
Prabir Pradhan5893d362023-11-17 04:30:40 +00006549TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6551
6552 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6553 ADISPLAY_ID_DEFAULT);
6554 left->setFrame(Rect(0, 0, 100, 100));
6555 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6556 "Right Window", ADISPLAY_ID_DEFAULT);
6557 right->setFrame(Rect(100, 0, 200, 100));
6558 sp<FakeWindowHandle> spy =
6559 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6560 spy->setFrame(Rect(0, 0, 200, 100));
6561 spy->setTrustedOverlay(true);
6562 spy->setSpy(true);
6563
6564 mDispatcher->onWindowInfosChanged(
6565 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6566
6567 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6568 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6569 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6570 mDispatcher->notifyMotion(notifyArgs);
6571
6572 const MotionEvent& leftEnter = left->consumeMotionEvent(
6573 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6574 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6575
6576 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6577 Not(WithEventId(notifyArgs.id)),
6578 Not(WithEventId(leftEnter.getId())),
6579 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6580
6581 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6582 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6583 {PointF{150, 50}});
6584 mDispatcher->notifyMotion(notifyArgs);
6585
6586 const MotionEvent& leftExit = left->consumeMotionEvent(
6587 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6588 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6589
6590 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6591 Not(WithEventId(notifyArgs.id)),
6592 Not(WithEventId(leftExit.getId())),
6593 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6594
6595 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6596}
6597
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006598class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6599protected:
6600 std::shared_ptr<FakeApplicationHandle> mApp;
6601 sp<FakeWindowHandle> mWindow;
6602
6603 virtual void SetUp() override {
6604 InputDispatcherTest::SetUp();
6605
6606 mApp = std::make_shared<FakeApplicationHandle>();
6607
6608 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6609 mWindow->setFrame(Rect(0, 0, 100, 100));
6610
6611 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6612 setFocusedWindow(mWindow);
6613 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6614 }
6615
6616 void setFallback(int32_t keycode) {
6617 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6618 return KeyEventBuilder(event).keyCode(keycode).build();
6619 });
6620 }
6621
6622 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6623 KeyEvent* event = mWindow->consumeKey(handled);
6624 ASSERT_NE(event, nullptr) << "Did not receive key event";
6625 ASSERT_THAT(*event, matcher);
6626 }
6627};
6628
6629TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6630 mDispatcher->notifyKey(
6631 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6632 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6633 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6634}
6635
6636TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6637 mDispatcher->notifyKey(
6638 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6639 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6640 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6641}
6642
6643TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6644 mDispatcher->notifyKey(
6645 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6646
6647 // Do not handle this key event.
6648 consumeKey(/*handled=*/false,
6649 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6650 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6651
6652 // Since the policy did not request any fallback to be generated, ensure there are no events.
6653 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6654}
6655
6656TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6657 setFallback(AKEYCODE_B);
6658 mDispatcher->notifyKey(
6659 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6660
6661 // Do not handle this key event.
6662 consumeKey(/*handled=*/false,
6663 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6664
6665 // Since the key was not handled, ensure the fallback event was dispatched instead.
6666 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6667 consumeKey(/*handled=*/true,
6668 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6669 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6670
6671 // Release the original key, and ensure the fallback key is also released.
6672 mDispatcher->notifyKey(
6673 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6674 consumeKey(/*handled=*/false,
6675 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6676 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6677 consumeKey(/*handled=*/true,
6678 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6679 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6680
6681 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6682 mWindow->assertNoEvents();
6683}
6684
6685TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6686 setFallback(AKEYCODE_B);
6687 mDispatcher->notifyKey(
6688 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6689
6690 // Do not handle this key event, but handle the fallback.
6691 consumeKey(/*handled=*/false,
6692 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6693 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6694 consumeKey(/*handled=*/true,
6695 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6696 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6697
6698 // Release the original key, and ensure the fallback key is also released.
6699 mDispatcher->notifyKey(
6700 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6701 // But this time, the app handles the original key.
6702 consumeKey(/*handled=*/true,
6703 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6704 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6705 // Ensure the fallback key is canceled.
6706 consumeKey(/*handled=*/true,
6707 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6708 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6709
6710 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6711 mWindow->assertNoEvents();
6712}
6713
6714TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6715 setFallback(AKEYCODE_B);
6716 mDispatcher->notifyKey(
6717 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6718
6719 // Do not handle this key event.
6720 consumeKey(/*handled=*/false,
6721 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6722 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6723 // App does not handle the fallback either, so ensure another fallback is not generated.
6724 setFallback(AKEYCODE_C);
6725 consumeKey(/*handled=*/false,
6726 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6727 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6728
6729 // Release the original key, and ensure the fallback key is also released.
6730 setFallback(AKEYCODE_B);
6731 mDispatcher->notifyKey(
6732 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6733 consumeKey(/*handled=*/false,
6734 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6735 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6736 consumeKey(/*handled=*/false,
6737 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6738 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6739
6740 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6741 mWindow->assertNoEvents();
6742}
6743
6744TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6745 setFallback(AKEYCODE_B);
6746 mDispatcher->notifyKey(
6747 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6748
6749 // Do not handle this key event, so fallback is generated.
6750 consumeKey(/*handled=*/false,
6751 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6752 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6753 consumeKey(/*handled=*/true,
6754 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6755 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6756
6757 // Release the original key, but assume the policy is misbehaving and it
6758 // generates an inconsistent fallback to the one from the DOWN event.
6759 setFallback(AKEYCODE_C);
6760 mDispatcher->notifyKey(
6761 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6762 consumeKey(/*handled=*/false,
6763 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6764 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6765 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6766 consumeKey(/*handled=*/true,
6767 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6768 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6769
6770 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6771 mWindow->assertNoEvents();
6772}
6773
6774TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6775 setFallback(AKEYCODE_B);
6776 mDispatcher->notifyKey(
6777 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6778
6779 // Do not handle this key event, so fallback is generated.
6780 consumeKey(/*handled=*/false,
6781 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6782 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6783 consumeKey(/*handled=*/true,
6784 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6785 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6786
6787 // The original key is canceled.
6788 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6789 .keyCode(AKEYCODE_A)
6790 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6791 .build());
6792 consumeKey(/*handled=*/false,
6793 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6794 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6795 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6796 // Ensure the fallback key is also canceled due to the original key being canceled.
6797 consumeKey(/*handled=*/true,
6798 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6799 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6800
6801 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6802 mWindow->assertNoEvents();
6803}
6804
Garfield Tan1c7bc862020-01-28 13:24:04 -08006805class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6806protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006807 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6808 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006809
Chris Yea209fde2020-07-22 13:54:51 -07006810 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006811 sp<FakeWindowHandle> mWindow;
6812
6813 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006814 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006815 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006816 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006817 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006818 ASSERT_EQ(OK, mDispatcher->start());
6819
6820 setUpWindow();
6821 }
6822
6823 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006824 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006825 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006826
Vishnu Nair47074b82020-08-14 11:54:47 -07006827 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006828 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006829 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006830 mWindow->consumeFocusEvent(true);
6831 }
6832
Chris Ye2ad95392020-09-01 13:44:44 -07006833 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006834 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006835 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006836 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006837 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006838
6839 // Window should receive key down event.
6840 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6841 }
6842
6843 void expectKeyRepeatOnce(int32_t repeatCount) {
6844 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006845 mWindow->consumeKeyEvent(
6846 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006847 }
6848
Chris Ye2ad95392020-09-01 13:44:44 -07006849 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006850 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006851 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006852 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006853 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006854
6855 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006856 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006857 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006858 }
6859};
6860
6861TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006862 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006863 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6864 expectKeyRepeatOnce(repeatCount);
6865 }
6866}
6867
6868TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006869 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006870 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6871 expectKeyRepeatOnce(repeatCount);
6872 }
Harry Cutts33476232023-01-30 19:57:29 +00006873 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006874 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006875 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6876 expectKeyRepeatOnce(repeatCount);
6877 }
6878}
6879
6880TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006881 sendAndConsumeKeyDown(/*deviceId=*/1);
6882 expectKeyRepeatOnce(/*repeatCount=*/1);
6883 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006884 mWindow->assertNoEvents();
6885}
6886
6887TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006888 sendAndConsumeKeyDown(/*deviceId=*/1);
6889 expectKeyRepeatOnce(/*repeatCount=*/1);
6890 sendAndConsumeKeyDown(/*deviceId=*/2);
6891 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006892 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006893 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006894 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006895 expectKeyRepeatOnce(/*repeatCount=*/2);
6896 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006897 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006898 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006899 mWindow->assertNoEvents();
6900}
6901
6902TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006903 sendAndConsumeKeyDown(/*deviceId=*/1);
6904 expectKeyRepeatOnce(/*repeatCount=*/1);
6905 sendAndConsumeKeyDown(/*deviceId=*/2);
6906 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006907 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006908 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006909 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006910 mWindow->assertNoEvents();
6911}
6912
liushenxiang42232912021-05-21 20:24:09 +08006913TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6914 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006915 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006916 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006917 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6918 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6919 mWindow->assertNoEvents();
6920}
6921
Garfield Tan1c7bc862020-01-28 13:24:04 -08006922TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006923 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006924 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006925 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006926 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006927 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6928 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6929 IdGenerator::getSource(repeatEvent->getId()));
6930 }
6931}
6932
6933TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006934 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006935 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006936
6937 std::unordered_set<int32_t> idSet;
6938 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006939 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006940 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6941 int32_t id = repeatEvent->getId();
6942 EXPECT_EQ(idSet.end(), idSet.find(id));
6943 idSet.insert(id);
6944 }
6945}
6946
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006947/* Test InputDispatcher for MultiDisplay */
6948class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6949public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006950 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006951 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006952
Chris Yea209fde2020-07-22 13:54:51 -07006953 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006954 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006955 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006956
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006957 // Set focus window for primary display, but focused display would be second one.
6958 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006959 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006960 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6961
Vishnu Nair958da932020-08-21 17:12:37 -07006962 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006963 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006964
Chris Yea209fde2020-07-22 13:54:51 -07006965 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006966 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006967 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006968 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006969 // Set focus display to second one.
6970 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6971 // Set focus window for second display.
6972 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006973 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006974 mDispatcher->onWindowInfosChanged(
6975 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006976 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006977 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006978 }
6979
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006980 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006981 InputDispatcherTest::TearDown();
6982
Chris Yea209fde2020-07-22 13:54:51 -07006983 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006984 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006985 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006986 windowInSecondary.clear();
6987 }
6988
6989protected:
Chris Yea209fde2020-07-22 13:54:51 -07006990 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006991 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006992 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006993 sp<FakeWindowHandle> windowInSecondary;
6994};
6995
6996TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6997 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006999 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007001 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007002 windowInSecondary->assertNoEvents();
7003
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007004 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007006 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007008 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007009 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007010}
7011
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007012TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007013 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007015 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007016 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007017 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007018 windowInSecondary->assertNoEvents();
7019
7020 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007022 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007023 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007024 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007025
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007026 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007027 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007028
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007029 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007030 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007031 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007032
7033 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007034 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007035 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007036 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007037 windowInSecondary->assertNoEvents();
7038}
7039
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007040// Test per-display input monitors for motion event.
7041TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007042 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007043 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007044 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007045 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007046
7047 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007049 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007051 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007052 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007053 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007054 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007055
7056 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007058 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007060 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007061 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007062 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007063 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007064
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007065 // Lift up the touch from the second display
7066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007067 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7069 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7070 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7071
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007072 // Test inject a non-pointer motion event.
7073 // If specific a display, it will dispatch to the focused window of particular display,
7074 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007078 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007079 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007080 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007081 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007082}
7083
7084// Test per-display input monitors for key event.
7085TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007086 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007087 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007088 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007089 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007090 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007091
7092 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007094 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007095 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007096 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007097 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007098 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007099}
7100
Vishnu Nair958da932020-08-21 17:12:37 -07007101TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7102 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007103 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007104 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007105 mDispatcher->onWindowInfosChanged(
7106 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7107 *windowInSecondary->getInfo()},
7108 {},
7109 0,
7110 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007111 setFocusedWindow(secondWindowInPrimary);
7112 windowInPrimary->consumeFocusEvent(false);
7113 secondWindowInPrimary->consumeFocusEvent(true);
7114
7115 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7117 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007118 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007119 windowInPrimary->assertNoEvents();
7120 windowInSecondary->assertNoEvents();
7121 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7122}
7123
Arthur Hungdfd528e2021-12-08 13:23:04 +00007124TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7125 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007126 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007127 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007128 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007129
7130 // Test touch down on primary display.
7131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007132 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7134 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7135 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7136
7137 // Test touch down on second display.
7138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007139 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7141 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7142 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7143
7144 // Trigger cancel touch.
7145 mDispatcher->cancelCurrentTouch();
7146 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7147 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7148 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7149 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7150
7151 // Test inject a move motion event, no window/monitor should receive the event.
7152 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007153 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007154 ADISPLAY_ID_DEFAULT, {110, 200}))
7155 << "Inject motion event should return InputEventInjectionResult::FAILED";
7156 windowInPrimary->assertNoEvents();
7157 monitorInPrimary.assertNoEvents();
7158
7159 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007160 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007161 SECOND_DISPLAY_ID, {110, 200}))
7162 << "Inject motion event should return InputEventInjectionResult::FAILED";
7163 windowInSecondary->assertNoEvents();
7164 monitorInSecondary.assertNoEvents();
7165}
7166
Jackal Guof9696682018-10-05 12:23:23 +08007167class InputFilterTest : public InputDispatcherTest {
7168protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007169 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7170 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007171 NotifyMotionArgs motionArgs;
7172
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007173 motionArgs =
7174 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007175 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007176 motionArgs =
7177 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007178 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007179 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007180 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007181 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007182 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007183 } else {
7184 mFakePolicy->assertFilterInputEventWasNotCalled();
7185 }
7186 }
7187
7188 void testNotifyKey(bool expectToBeFiltered) {
7189 NotifyKeyArgs keyArgs;
7190
7191 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007192 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007193 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007194 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007195 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007196
7197 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007198 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007199 } else {
7200 mFakePolicy->assertFilterInputEventWasNotCalled();
7201 }
7202 }
7203};
7204
7205// Test InputFilter for MotionEvent
7206TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7207 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007208 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7209 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007210
7211 // Enable InputFilter
7212 mDispatcher->setInputFilterEnabled(true);
7213 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007214 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7215 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007216
7217 // Disable InputFilter
7218 mDispatcher->setInputFilterEnabled(false);
7219 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007220 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7221 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007222}
7223
7224// Test InputFilter for KeyEvent
7225TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7226 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007227 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007228
7229 // Enable InputFilter
7230 mDispatcher->setInputFilterEnabled(true);
7231 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007232 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007233
7234 // Disable InputFilter
7235 mDispatcher->setInputFilterEnabled(false);
7236 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007237 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007238}
7239
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007240// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7241// logical display coordinate space.
7242TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7243 ui::Transform firstDisplayTransform;
7244 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7245 ui::Transform secondDisplayTransform;
7246 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7247
7248 std::vector<gui::DisplayInfo> displayInfos(2);
7249 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7250 displayInfos[0].transform = firstDisplayTransform;
7251 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7252 displayInfos[1].transform = secondDisplayTransform;
7253
Patrick Williamsd828f302023-04-28 17:52:08 -05007254 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007255
7256 // Enable InputFilter
7257 mDispatcher->setInputFilterEnabled(true);
7258
7259 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007260 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7261 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007262}
7263
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007264class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7265protected:
7266 virtual void SetUp() override {
7267 InputDispatcherTest::SetUp();
7268
7269 /**
7270 * We don't need to enable input filter to test the injected event policy, but we enabled it
7271 * here to make the tests more realistic, since this policy only matters when inputfilter is
7272 * on.
7273 */
7274 mDispatcher->setInputFilterEnabled(true);
7275
7276 std::shared_ptr<InputApplicationHandle> application =
7277 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007278 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7279 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007280
7281 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7282 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007283 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007284 setFocusedWindow(mWindow);
7285 mWindow->consumeFocusEvent(true);
7286 }
7287
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007288 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7289 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007290 KeyEvent event;
7291
7292 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7293 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7294 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007295 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007296 const int32_t additionalPolicyFlags =
7297 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007300 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007301 policyFlags | additionalPolicyFlags));
7302
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007303 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007304 }
7305
7306 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7307 int32_t flags) {
7308 MotionEvent event;
7309 PointerProperties pointerProperties[1];
7310 PointerCoords pointerCoords[1];
7311 pointerProperties[0].clear();
7312 pointerProperties[0].id = 0;
7313 pointerCoords[0].clear();
7314 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7315 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7316
7317 ui::Transform identityTransform;
7318 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7319 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7320 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7321 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7322 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007323 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007324 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007325 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007326
7327 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007329 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007330 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007331 policyFlags | additionalPolicyFlags));
7332
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007333 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007334 }
7335
7336private:
7337 sp<FakeWindowHandle> mWindow;
7338};
7339
7340TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007341 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7342 // filter. Without it, the event will no different from a regularly injected event, and the
7343 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007344 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7345 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007346}
7347
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007348TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007349 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007350 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007351 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7352}
7353
7354TEST_F(InputFilterInjectionPolicyTest,
7355 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7356 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007357 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007358 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007359}
7360
7361TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007362 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7363 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007364}
7365
chaviwfd6d3512019-03-25 13:23:49 -07007366class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007367 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007368 InputDispatcherTest::SetUp();
7369
Chris Yea209fde2020-07-22 13:54:51 -07007370 std::shared_ptr<FakeApplicationHandle> application =
7371 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007372 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007373 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007374 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007375
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007376 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007377 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007378 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007379
7380 // Set focused application.
7381 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007382 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007383
7384 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007385 mDispatcher->onWindowInfosChanged(
7386 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007387 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007388 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007389 }
7390
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007391 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007392 InputDispatcherTest::TearDown();
7393
7394 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007395 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007396 }
7397
7398protected:
7399 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007400 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007401 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007402};
7403
7404// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7405// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7406// the onPointerDownOutsideFocus callback.
7407TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007409 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007410 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007411 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007412 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007414 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007415 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7416}
7417
7418// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7419// DOWN on the window that doesn't have focus. Ensure no window received the
7420// onPointerDownOutsideFocus callback.
7421TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007423 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7424 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007425 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007426 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007427
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007428 ASSERT_TRUE(mDispatcher->waitForIdle());
7429 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007430}
7431
7432// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7433// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7434TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007436 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007437 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007438 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007439
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007440 ASSERT_TRUE(mDispatcher->waitForIdle());
7441 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007442}
7443
7444// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7445// DOWN on the window that already has focus. Ensure no window received the
7446// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007447TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007449 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007450 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007452 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007453
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007454 ASSERT_TRUE(mDispatcher->waitForIdle());
7455 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007456}
7457
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007458// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7459// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7460TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7461 const MotionEvent event =
7462 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7463 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007465 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7466 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7469 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7470
7471 ASSERT_TRUE(mDispatcher->waitForIdle());
7472 mFakePolicy->assertOnPointerDownWasNotCalled();
7473 // Ensure that the unfocused window did not receive any FOCUS events.
7474 mUnfocusedWindow->assertNoEvents();
7475}
7476
chaviwaf87b3e2019-10-01 16:59:28 -07007477// These tests ensures we can send touch events to a single client when there are multiple input
7478// windows that point to the same client token.
7479class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7480 virtual void SetUp() override {
7481 InputDispatcherTest::SetUp();
7482
Chris Yea209fde2020-07-22 13:54:51 -07007483 std::shared_ptr<FakeApplicationHandle> application =
7484 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007485 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7486 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007487 mWindow1->setFrame(Rect(0, 0, 100, 100));
7488
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007489 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7490 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007491 mWindow2->setFrame(Rect(100, 100, 200, 200));
7492
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007493 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007494 }
7495
7496protected:
7497 sp<FakeWindowHandle> mWindow1;
7498 sp<FakeWindowHandle> mWindow2;
7499
7500 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007501 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007502 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7503 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007504 }
7505
7506 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7507 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007508 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007509 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007510
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 ASSERT_NE(nullptr, motionEvent)
7512 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007513
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007514 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007515 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007516
7517 for (size_t i = 0; i < points.size(); i++) {
7518 float expectedX = points[i].x;
7519 float expectedY = points[i].y;
7520
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007521 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007522 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007523 << ", got " << motionEvent->getX(i);
7524 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007525 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007526 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007527 }
7528 }
chaviw9eaa22c2020-07-01 16:21:27 -07007529
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007530 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007531 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007532 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7533 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007534
7535 // Always consume from window1 since it's the window that has the InputReceiver
7536 consumeMotionEvent(mWindow1, action, expectedPoints);
7537 }
chaviwaf87b3e2019-10-01 16:59:28 -07007538};
7539
7540TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7541 // Touch Window 1
7542 PointF touchedPoint = {10, 10};
7543 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007544 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007545
7546 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007547 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007548
7549 // Touch Window 2
7550 touchedPoint = {150, 150};
7551 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007552 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007553}
7554
chaviw9eaa22c2020-07-01 16:21:27 -07007555TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7556 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007557 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007558 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007559
7560 // Touch Window 1
7561 PointF touchedPoint = {10, 10};
7562 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007563 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007564 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007565 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007566
7567 // Touch Window 2
7568 touchedPoint = {150, 150};
7569 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007570 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7571 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007572
chaviw9eaa22c2020-07-01 16:21:27 -07007573 // Update the transform so rotation is set
7574 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007575 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007576 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7577 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007578}
7579
chaviw9eaa22c2020-07-01 16:21:27 -07007580TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007581 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007582 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007583
7584 // Touch Window 1
7585 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7586 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007587 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007588
7589 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007590 touchedPoints.push_back(PointF{150, 150});
7591 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007592 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007593
chaviw9eaa22c2020-07-01 16:21:27 -07007594 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007595 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007596 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007597
chaviw9eaa22c2020-07-01 16:21:27 -07007598 // Update the transform so rotation is set for Window 2
7599 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007600 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007601 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007602 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007603}
7604
chaviw9eaa22c2020-07-01 16:21:27 -07007605TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007606 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007607 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007608
7609 // Touch Window 1
7610 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7611 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007612 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007613
7614 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007615 touchedPoints.push_back(PointF{150, 150});
7616 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007617
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007618 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007619
7620 // Move both windows
7621 touchedPoints = {{20, 20}, {175, 175}};
7622 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7623 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7624
chaviw9eaa22c2020-07-01 16:21:27 -07007625 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007626
chaviw9eaa22c2020-07-01 16:21:27 -07007627 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007628 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007629 expectedPoints.pop_back();
7630
7631 // Touch Window 2
7632 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007633 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007634 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007635 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007636
7637 // Move both windows
7638 touchedPoints = {{20, 20}, {175, 175}};
7639 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7640 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7641
7642 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007643}
7644
7645TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7646 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007647 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007648
7649 // Touch Window 1
7650 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7651 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007652 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007653
7654 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007655 touchedPoints.push_back(PointF{150, 150});
7656 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007657
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007658 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007659
7660 // Move both windows
7661 touchedPoints = {{20, 20}, {175, 175}};
7662 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7663 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7664
chaviw9eaa22c2020-07-01 16:21:27 -07007665 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007666}
7667
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007668/**
7669 * When one of the windows is slippery, the touch should not slip into the other window with the
7670 * same input channel.
7671 */
7672TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7673 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007674 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007675
7676 // Touch down in window 1
7677 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7678 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7679 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7680
7681 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7682 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7683 // getting generated.
7684 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7685 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7686
7687 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7688}
7689
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007690/**
7691 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7692 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7693 * that the pointer is hovering over may have a different transform.
7694 */
7695TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007696 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007697
7698 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007699 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7700 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7701 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007702 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7703 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007704 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007705 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7706 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7707 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007708 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7709 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7710 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7711}
7712
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007713class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7714 virtual void SetUp() override {
7715 InputDispatcherTest::SetUp();
7716
Chris Yea209fde2020-07-22 13:54:51 -07007717 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007718 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007719 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7720 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007721 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007722 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007723 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007724
7725 // Set focused application.
7726 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007728 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007729 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007730 mWindow->consumeFocusEvent(true);
7731 }
7732
7733 virtual void TearDown() override {
7734 InputDispatcherTest::TearDown();
7735 mWindow.clear();
7736 }
7737
7738protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007739 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007740 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007741 sp<FakeWindowHandle> mWindow;
7742 static constexpr PointF WINDOW_LOCATION = {20, 20};
7743
7744 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007745 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7746 .x(WINDOW_LOCATION.x)
7747 .y(WINDOW_LOCATION.y);
7748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7749 .pointer(touchingPointer)
7750 .build());
7751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7752 .pointer(touchingPointer)
7753 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007754 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007755
7756 sp<FakeWindowHandle> addSpyWindow() {
7757 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007758 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007759 spy->setTrustedOverlay(true);
7760 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007761 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007762 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007763 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007764 return spy;
7765 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007766};
7767
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007768// Send a tap and respond, which should not cause an ANR.
7769TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7770 tapOnWindow();
7771 mWindow->consumeMotionDown();
7772 mWindow->consumeMotionUp();
7773 ASSERT_TRUE(mDispatcher->waitForIdle());
7774 mFakePolicy->assertNotifyAnrWasNotCalled();
7775}
7776
7777// Send a regular key and respond, which should not cause an ANR.
7778TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007780 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7781 ASSERT_TRUE(mDispatcher->waitForIdle());
7782 mFakePolicy->assertNotifyAnrWasNotCalled();
7783}
7784
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007785TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7786 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007787 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007788 mWindow->consumeFocusEvent(false);
7789
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007790 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007791 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7792 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007793 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007795 // Key will not go to window because we have no focused window.
7796 // The 'no focused window' ANR timer should start instead.
7797
7798 // Now, the focused application goes away.
7799 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7800 // The key should get dropped and there should be no ANR.
7801
7802 ASSERT_TRUE(mDispatcher->waitForIdle());
7803 mFakePolicy->assertNotifyAnrWasNotCalled();
7804}
7805
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007806// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007807// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7808// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007809TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007811 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007812 WINDOW_LOCATION));
7813
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007814 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7815 ASSERT_TRUE(sequenceNum);
7816 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007817 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007818
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007819 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007820 mWindow->consumeMotionEvent(
7821 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007822 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007823 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007824}
7825
7826// Send a key to the app and have the app not respond right away.
7827TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7828 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007830 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7831 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007832 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007833 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007834 ASSERT_TRUE(mDispatcher->waitForIdle());
7835}
7836
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007837// We have a focused application, but no focused window
7838TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007839 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007840 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007841 mWindow->consumeFocusEvent(false);
7842
7843 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007846 WINDOW_LOCATION));
7847 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7848 mDispatcher->waitForIdle();
7849 mFakePolicy->assertNotifyAnrWasNotCalled();
7850
7851 // Once a focused event arrives, we get an ANR for this application
7852 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7853 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007854 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007855 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007856 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007858 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007859 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007860 ASSERT_TRUE(mDispatcher->waitForIdle());
7861}
7862
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007863/**
7864 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7865 * there will not be an ANR.
7866 */
7867TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7868 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007869 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007870 mWindow->consumeFocusEvent(false);
7871
7872 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007873 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7874 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007875 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7876 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7877
7878 // Define a valid key down event that is stale (too old).
7879 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007880 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007881 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007882
7883 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7884
7885 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007886 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007887 InputEventInjectionSync::WAIT_FOR_RESULT,
7888 INJECT_EVENT_TIMEOUT, policyFlags);
7889 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7890 << "Injection should fail because the event is stale";
7891
7892 ASSERT_TRUE(mDispatcher->waitForIdle());
7893 mFakePolicy->assertNotifyAnrWasNotCalled();
7894 mWindow->assertNoEvents();
7895}
7896
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007897// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007898// Make sure that we don't notify policy twice about the same ANR.
7899TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007900 const std::chrono::duration appTimeout = 400ms;
7901 mApplication->setDispatchingTimeout(appTimeout);
7902 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7903
Vishnu Nair47074b82020-08-14 11:54:47 -07007904 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007905 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007906 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007907
7908 // Once a focused event arrives, we get an ANR for this application
7909 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7910 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007911 const std::chrono::duration eventInjectionTimeout = 100ms;
7912 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007913 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007914 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007915 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7916 /*allowKeyRepeat=*/false);
7917 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7918 << "result=" << ftl::enum_string(result);
7919 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7920 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7921 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7922 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007923
Vishnu Naire4df8752022-09-08 09:17:55 -07007924 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007925 // ANR should not be raised again. It is up to policy to do that if it desires.
7926 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007927
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007928 // If we now get a focused window, the ANR should stop, but the policy handles that via
7929 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007930 ASSERT_TRUE(mDispatcher->waitForIdle());
7931}
7932
7933// We have a focused application, but no focused window
7934TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007935 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007936 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007937 mWindow->consumeFocusEvent(false);
7938
7939 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007940 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007941
Vishnu Naire4df8752022-09-08 09:17:55 -07007942 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7943 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007944
7945 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007946 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007947 ASSERT_TRUE(mDispatcher->waitForIdle());
7948 mWindow->assertNoEvents();
7949}
7950
7951/**
7952 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7953 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7954 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7955 * the ANR mechanism should still work.
7956 *
7957 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7958 * DOWN event, while not responding on the second one.
7959 */
7960TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7961 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007962 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007963 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7964 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7965 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007966 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007967
7968 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007969 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007970 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7971 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7972 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007973 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007974
7975 // We have now sent down and up. Let's consume first event and then ANR on the second.
7976 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7977 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007978 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007979}
7980
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007981// A spy window can receive an ANR
7982TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7983 sp<FakeWindowHandle> spy = addSpyWindow();
7984
7985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007986 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007987 WINDOW_LOCATION));
7988 mWindow->consumeMotionDown();
7989
7990 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7991 ASSERT_TRUE(sequenceNum);
7992 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007993 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007994
7995 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007996 spy->consumeMotionEvent(
7997 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007998 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007999 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008000}
8001
8002// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008003// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008004TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8005 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008006
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008008 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008009 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008011
8012 // Stuck on the ACTION_UP
8013 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008014 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008015
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008016 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008018 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8019 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008020
8021 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8022 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008023 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008024 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008025 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026}
8027
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008028// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008029// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008030TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8031 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008032
8033 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008034 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8035 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008036
8037 mWindow->consumeMotionDown();
8038 // Stuck on the ACTION_UP
8039 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008040 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008041
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008042 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008043 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008044 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8045 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008046
8047 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8048 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008049 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008050 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008051 spy->assertNoEvents();
8052}
8053
8054TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008055 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008056
Prabir Pradhanfb549072023-10-05 19:17:36 +00008057 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008058
8059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008060 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008061 WINDOW_LOCATION));
8062
8063 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8064 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8065 ASSERT_TRUE(consumeSeq);
8066
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008067 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8068 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008069
8070 monitor.finishEvent(*consumeSeq);
8071 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8072
8073 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008074 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008075}
8076
8077// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8078// process events, you don't get an anr. When the window later becomes unresponsive again, you
8079// get an ANR again.
8080// 1. tap -> block on ACTION_UP -> receive ANR
8081// 2. consume all pending events (= queue becomes healthy again)
8082// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8083TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8084 tapOnWindow();
8085
8086 mWindow->consumeMotionDown();
8087 // Block on ACTION_UP
8088 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008089 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8091 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008092 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008093 mWindow->assertNoEvents();
8094
8095 tapOnWindow();
8096 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008097 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008098 mWindow->consumeMotionUp();
8099
8100 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008101 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008102 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008103 mWindow->assertNoEvents();
8104}
8105
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008106// If a connection remains unresponsive for a while, make sure policy is only notified once about
8107// it.
8108TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008110 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008111 WINDOW_LOCATION));
8112
8113 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008114 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008115 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008116 // 'notifyConnectionUnresponsive' should only be called once per connection
8117 mFakePolicy->assertNotifyAnrWasNotCalled();
8118 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008119 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008120 mWindow->consumeMotionEvent(
8121 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008122 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008123 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008124 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008125 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008126}
8127
8128/**
8129 * 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 -07008130 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131 *
8132 * Warning!!!
8133 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8134 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008135 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008136 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8137 *
8138 * If that value changes, this test should also change.
8139 */
8140TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8141 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008142 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008143
8144 tapOnWindow();
8145 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8146 ASSERT_TRUE(downSequenceNum);
8147 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8148 ASSERT_TRUE(upSequenceNum);
8149 // Don't finish the events yet, and send a key
8150 // Injection will "succeed" because we will eventually give up and send the key to the focused
8151 // window even if motions are still being processed. But because the injection timeout is short,
8152 // we will receive INJECTION_TIMED_OUT as the result.
8153
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008154 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008155 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8156 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008157 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008158 // Key will not be sent to the window, yet, because the window is still processing events
8159 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008160 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8161 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8162 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8163 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008164
8165 std::this_thread::sleep_for(500ms);
8166 // if we wait long enough though, dispatcher will give up, and still send the key
8167 // to the focused window, even though we have not yet finished the motion event
8168 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8169 mWindow->finishEvent(*downSequenceNum);
8170 mWindow->finishEvent(*upSequenceNum);
8171}
8172
8173/**
8174 * If a window is processing a motion event, and then a key event comes in, the key event should
8175 * not go to the focused window until the motion is processed.
8176 * If then a new motion comes in, then the pending key event should be going to the currently
8177 * focused window right away.
8178 */
8179TEST_F(InputDispatcherSingleWindowAnr,
8180 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8181 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008182 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008183
8184 tapOnWindow();
8185 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8186 ASSERT_TRUE(downSequenceNum);
8187 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8188 ASSERT_TRUE(upSequenceNum);
8189 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008190 mDispatcher->notifyKey(
8191 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8192 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8193 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008195 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8196 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8197 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8198 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008199
8200 // Now tap down again. It should cause the pending key to go to the focused window right away.
8201 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008202 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8203 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008204 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8205 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008206 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8207 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208 mWindow->assertNoEvents();
8209}
8210
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008211/**
8212 * Send an event to the app and have the app not respond right away.
8213 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8214 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8215 * At some point, the window becomes responsive again.
8216 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8217 */
8218TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8220 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8221 .build());
8222
8223 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8224 ASSERT_TRUE(sequenceNum);
8225 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8226 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8227
8228 mWindow->finishEvent(*sequenceNum);
8229 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8230 ASSERT_TRUE(mDispatcher->waitForIdle());
8231 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8232
8233 // Now that the window is responsive, let's continue the gesture.
8234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8235 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8236 .build());
8237
8238 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, 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
8243 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8244 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8245 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8246 .build());
8247 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8248 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8249 .build());
8250 // We already canceled this pointer, so the window shouldn't get any new events.
8251 mWindow->assertNoEvents();
8252
8253 // Start another one.
8254 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8255 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8256 .build());
8257 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8258}
8259
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008260class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8261 virtual void SetUp() override {
8262 InputDispatcherTest::SetUp();
8263
Chris Yea209fde2020-07-22 13:54:51 -07008264 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008265 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008266 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8267 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008268 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008269 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008270 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008271
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008272 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8273 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008274 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008275 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008276
8277 // Set focused application.
8278 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008279 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280
8281 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008282 mDispatcher->onWindowInfosChanged(
8283 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008284 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008285 mFocusedWindow->consumeFocusEvent(true);
8286 }
8287
8288 virtual void TearDown() override {
8289 InputDispatcherTest::TearDown();
8290
8291 mUnfocusedWindow.clear();
8292 mFocusedWindow.clear();
8293 }
8294
8295protected:
Chris Yea209fde2020-07-22 13:54:51 -07008296 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008297 sp<FakeWindowHandle> mUnfocusedWindow;
8298 sp<FakeWindowHandle> mFocusedWindow;
8299 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8300 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8301 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8302
8303 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8304
8305 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8306
8307private:
8308 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008310 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008311 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008313 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008314 location));
8315 }
8316};
8317
8318// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8319// should be ANR'd first.
8320TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008322 injectMotionEvent(*mDispatcher,
8323 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8324 AINPUT_SOURCE_TOUCHSCREEN)
8325 .pointer(PointerBuilder(0, ToolType::FINGER)
8326 .x(FOCUSED_WINDOW_LOCATION.x)
8327 .y(FOCUSED_WINDOW_LOCATION.y))
8328 .build()));
8329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8330 injectMotionEvent(*mDispatcher,
8331 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8332 AINPUT_SOURCE_TOUCHSCREEN)
8333 .pointer(PointerBuilder(0, ToolType::FINGER)
8334 .x(FOCUSED_WINDOW_LOCATION.x)
8335 .y(FOCUSED_WINDOW_LOCATION.y))
8336 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008337 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008338 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008339 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008340 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008341 // We consumed all events, so no ANR
8342 ASSERT_TRUE(mDispatcher->waitForIdle());
8343 mFakePolicy->assertNotifyAnrWasNotCalled();
8344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008346 injectMotionEvent(*mDispatcher,
8347 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8348 AINPUT_SOURCE_TOUCHSCREEN)
8349 .pointer(PointerBuilder(0, ToolType::FINGER)
8350 .x(FOCUSED_WINDOW_LOCATION.x)
8351 .y(FOCUSED_WINDOW_LOCATION.y))
8352 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008353 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8354 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008355
8356 const std::chrono::duration timeout =
8357 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008358 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008359
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008360 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008361 mFocusedWindow->consumeMotionDown();
8362 // This cancel is generated because the connection was unresponsive
8363 mFocusedWindow->consumeMotionCancel();
8364 mFocusedWindow->assertNoEvents();
8365 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008366 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008367 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8368 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008369 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008370}
8371
8372// If we have 2 windows with identical timeouts that are both unresponsive,
8373// it doesn't matter which order they should have ANR.
8374// But we should receive ANR for both.
8375TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8376 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008377 mUnfocusedWindow->setDispatchingTimeout(
8378 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008379 mDispatcher->onWindowInfosChanged(
8380 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008381
8382 tapOnFocusedWindow();
8383 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008384 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008385 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8386 mFocusedWindow->getDispatchingTimeout(
8387 DISPATCHING_TIMEOUT)),
8388 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8389
8390 ASSERT_THAT(anrConnectionTokens,
8391 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8392 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008393
8394 ASSERT_TRUE(mDispatcher->waitForIdle());
8395 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008396
8397 mFocusedWindow->consumeMotionDown();
8398 mFocusedWindow->consumeMotionUp();
8399 mUnfocusedWindow->consumeMotionOutside();
8400
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008401 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8402 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008403
8404 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008405 ASSERT_THAT(responsiveTokens,
8406 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8407 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008408 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008409}
8410
8411// If a window is already not responding, the second tap on the same window should be ignored.
8412// We should also log an error to account for the dropped event (not tested here).
8413// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8414TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8415 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008416 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008417 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008418 // Receive the events, but don't respond
8419 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8420 ASSERT_TRUE(downEventSequenceNum);
8421 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8422 ASSERT_TRUE(upEventSequenceNum);
8423 const std::chrono::duration timeout =
8424 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008425 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008426
8427 // Tap once again
8428 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008429 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008430 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008431 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008432 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008433 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008434 FOCUSED_WINDOW_LOCATION));
8435 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8436 // valid touch target
8437 mUnfocusedWindow->assertNoEvents();
8438
8439 // Consume the first tap
8440 mFocusedWindow->finishEvent(*downEventSequenceNum);
8441 mFocusedWindow->finishEvent(*upEventSequenceNum);
8442 ASSERT_TRUE(mDispatcher->waitForIdle());
8443 // The second tap did not go to the focused window
8444 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008445 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008446 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8447 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008448 mFakePolicy->assertNotifyAnrWasNotCalled();
8449}
8450
8451// If you tap outside of all windows, there will not be ANR
8452TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008453 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008454 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008455 LOCATION_OUTSIDE_ALL_WINDOWS));
8456 ASSERT_TRUE(mDispatcher->waitForIdle());
8457 mFakePolicy->assertNotifyAnrWasNotCalled();
8458}
8459
8460// Since the focused window is paused, tapping on it should not produce any events
8461TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8462 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008463 mDispatcher->onWindowInfosChanged(
8464 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008465
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008466 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008468 FOCUSED_WINDOW_LOCATION));
8469
8470 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8471 ASSERT_TRUE(mDispatcher->waitForIdle());
8472 // Should not ANR because the window is paused, and touches shouldn't go to it
8473 mFakePolicy->assertNotifyAnrWasNotCalled();
8474
8475 mFocusedWindow->assertNoEvents();
8476 mUnfocusedWindow->assertNoEvents();
8477}
8478
8479/**
8480 * 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 -07008481 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008482 * If a different window becomes focused at this time, the key should go to that window instead.
8483 *
8484 * Warning!!!
8485 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8486 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008487 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008488 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8489 *
8490 * If that value changes, this test should also change.
8491 */
8492TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8493 // Set a long ANR timeout to prevent it from triggering
8494 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008495 mDispatcher->onWindowInfosChanged(
8496 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008497
8498 tapOnUnfocusedWindow();
8499 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8500 ASSERT_TRUE(downSequenceNum);
8501 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8502 ASSERT_TRUE(upSequenceNum);
8503 // Don't finish the events yet, and send a key
8504 // Injection will succeed because we will eventually give up and send the key to the focused
8505 // window even if motions are still being processed.
8506
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008507 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008508 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8509 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008511 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008512 // and the key remains pending, waiting for the touch events to be processed.
8513 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8514 // under the hood.
8515 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8516 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517
8518 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008519 mFocusedWindow->setFocusable(false);
8520 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008521 mDispatcher->onWindowInfosChanged(
8522 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008523 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008524
8525 // Focus events should precede the key events
8526 mUnfocusedWindow->consumeFocusEvent(true);
8527 mFocusedWindow->consumeFocusEvent(false);
8528
8529 // Finish the tap events, which should unblock dispatcher
8530 mUnfocusedWindow->finishEvent(*downSequenceNum);
8531 mUnfocusedWindow->finishEvent(*upSequenceNum);
8532
8533 // Now that all queues are cleared and no backlog in the connections, the key event
8534 // can finally go to the newly focused "mUnfocusedWindow".
8535 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8536 mFocusedWindow->assertNoEvents();
8537 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008538 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008539}
8540
8541// When the touch stream is split across 2 windows, and one of them does not respond,
8542// then ANR should be raised and the touch should be canceled for the unresponsive window.
8543// The other window should not be affected by that.
8544TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8545 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008546 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8547 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8548 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008549 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008550 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008551
8552 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008553 mDispatcher->notifyMotion(
8554 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8555 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008556
8557 const std::chrono::duration timeout =
8558 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008559 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008560
8561 mUnfocusedWindow->consumeMotionDown();
8562 mFocusedWindow->consumeMotionDown();
8563 // Focused window may or may not receive ACTION_MOVE
8564 // But it should definitely receive ACTION_CANCEL due to the ANR
8565 InputEvent* event;
8566 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8567 ASSERT_TRUE(moveOrCancelSequenceNum);
8568 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8569 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008570 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008571 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8572 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8573 mFocusedWindow->consumeMotionCancel();
8574 } else {
8575 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8576 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008577 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008578 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8579 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008580
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008581 mUnfocusedWindow->assertNoEvents();
8582 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008583 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008584}
8585
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008586/**
8587 * If we have no focused window, and a key comes in, we start the ANR timer.
8588 * The focused application should add a focused window before the timer runs out to prevent ANR.
8589 *
8590 * If the user touches another application during this time, the key should be dropped.
8591 * Next, if a new focused window comes in, without toggling the focused application,
8592 * then no ANR should occur.
8593 *
8594 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8595 * but in some cases the policy may not update the focused application.
8596 */
8597TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8598 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8599 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008600 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008601 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8602 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8603 mFocusedWindow->setFocusable(false);
8604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008605 mDispatcher->onWindowInfosChanged(
8606 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008607 mFocusedWindow->consumeFocusEvent(false);
8608
8609 // Send a key. The ANR timer should start because there is no focused window.
8610 // 'focusedApplication' will get blamed if this timer completes.
8611 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008612 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008613 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8614 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008615 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008617
8618 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8619 // then the injected touches won't cause the focused event to get dropped.
8620 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8621 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8622 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8623 // For this test, it means that the key would get delivered to the window once it becomes
8624 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008625 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008626
8627 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008628 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8629 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8630 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008631
8632 // We do not consume the motion right away, because that would require dispatcher to first
8633 // process (== drop) the key event, and by that time, ANR will be raised.
8634 // Set the focused window first.
8635 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008636 mDispatcher->onWindowInfosChanged(
8637 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008638 setFocusedWindow(mFocusedWindow);
8639 mFocusedWindow->consumeFocusEvent(true);
8640 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8641 // to another application. This could be a bug / behaviour in the policy.
8642
8643 mUnfocusedWindow->consumeMotionDown();
8644
8645 ASSERT_TRUE(mDispatcher->waitForIdle());
8646 // Should not ANR because we actually have a focused window. It was just added too slowly.
8647 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8648}
8649
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008650// These tests ensure we cannot send touch events to a window that's positioned behind a window
8651// that has feature NO_INPUT_CHANNEL.
8652// Layout:
8653// Top (closest to user)
8654// mNoInputWindow (above all windows)
8655// mBottomWindow
8656// Bottom (furthest from user)
8657class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8658 virtual void SetUp() override {
8659 InputDispatcherTest::SetUp();
8660
8661 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008662 mNoInputWindow =
8663 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8664 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008665 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008666 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008667 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8668 // It's perfectly valid for this window to not have an associated input channel
8669
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008670 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8671 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008672 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008674 mDispatcher->onWindowInfosChanged(
8675 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008676 }
8677
8678protected:
8679 std::shared_ptr<FakeApplicationHandle> mApplication;
8680 sp<FakeWindowHandle> mNoInputWindow;
8681 sp<FakeWindowHandle> mBottomWindow;
8682};
8683
8684TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8685 PointF touchedPoint = {10, 10};
8686
Prabir Pradhan678438e2023-04-13 19:32:51 +00008687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8688 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8689 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008690
8691 mNoInputWindow->assertNoEvents();
8692 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8693 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8694 // and therefore should prevent mBottomWindow from receiving touches
8695 mBottomWindow->assertNoEvents();
8696}
8697
8698/**
8699 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8700 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8701 */
8702TEST_F(InputDispatcherMultiWindowOcclusionTests,
8703 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008704 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8705 "Window with input channel and NO_INPUT_CHANNEL",
8706 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008707
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008708 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008709 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008710 mDispatcher->onWindowInfosChanged(
8711 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008712
8713 PointF touchedPoint = {10, 10};
8714
Prabir Pradhan678438e2023-04-13 19:32:51 +00008715 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8716 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8717 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008718
8719 mNoInputWindow->assertNoEvents();
8720 mBottomWindow->assertNoEvents();
8721}
8722
Vishnu Nair958da932020-08-21 17:12:37 -07008723class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8724protected:
8725 std::shared_ptr<FakeApplicationHandle> mApp;
8726 sp<FakeWindowHandle> mWindow;
8727 sp<FakeWindowHandle> mMirror;
8728
8729 virtual void SetUp() override {
8730 InputDispatcherTest::SetUp();
8731 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008732 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8733 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8734 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008735 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8736 mWindow->setFocusable(true);
8737 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008738 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008739 }
8740};
8741
8742TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8743 // Request focus on a mirrored window
8744 setFocusedWindow(mMirror);
8745
8746 // window gets focused
8747 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008749 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008750 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8751}
8752
8753// A focused & mirrored window remains focused only if the window and its mirror are both
8754// focusable.
8755TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8756 setFocusedWindow(mMirror);
8757
8758 // window gets focused
8759 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008761 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008762 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008764 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008765 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8766
8767 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008768 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008769
8770 // window loses focus since one of the windows associated with the token in not focusable
8771 mWindow->consumeFocusEvent(false);
8772
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008773 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008774 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008775 mWindow->assertNoEvents();
8776}
8777
8778// A focused & mirrored window remains focused until the window and its mirror both become
8779// invisible.
8780TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8781 setFocusedWindow(mMirror);
8782
8783 // window gets focused
8784 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008786 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008787 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008789 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008790 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8791
8792 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008794
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008796 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008797 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008799 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008800 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8801
8802 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008803 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008804
8805 // window loses focus only after all windows associated with the token become invisible.
8806 mWindow->consumeFocusEvent(false);
8807
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008808 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008809 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008810 mWindow->assertNoEvents();
8811}
8812
8813// A focused & mirrored window remains focused until both windows are removed.
8814TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8815 setFocusedWindow(mMirror);
8816
8817 // window gets focused
8818 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008820 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008821 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008823 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008824 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8825
8826 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008827 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008828
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008830 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008831 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008833 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008834 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8835
8836 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008837 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008838 mWindow->consumeFocusEvent(false);
8839
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008840 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008841 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008842 mWindow->assertNoEvents();
8843}
8844
8845// Focus request can be pending until one window becomes visible.
8846TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8847 // Request focus on an invisible mirror.
8848 mWindow->setVisible(false);
8849 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008850 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008851 setFocusedWindow(mMirror);
8852
8853 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008855 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8856 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008857
8858 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008859 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008860
8861 // window gets focused
8862 mWindow->consumeFocusEvent(true);
8863 // window gets the pending key event
8864 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8865}
Prabir Pradhan99987712020-11-10 18:43:05 -08008866
8867class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8868protected:
8869 std::shared_ptr<FakeApplicationHandle> mApp;
8870 sp<FakeWindowHandle> mWindow;
8871 sp<FakeWindowHandle> mSecondWindow;
8872
8873 void SetUp() override {
8874 InputDispatcherTest::SetUp();
8875 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008876 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008877 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008878 mSecondWindow =
8879 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008880 mSecondWindow->setFocusable(true);
8881
8882 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008883 mDispatcher->onWindowInfosChanged(
8884 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008885
8886 setFocusedWindow(mWindow);
8887 mWindow->consumeFocusEvent(true);
8888 }
8889
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008890 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008891 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008892 }
8893
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008894 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8895 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008896 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008897 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8898 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008899 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008900 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008901 }
8902};
8903
8904TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8905 // Ensure that capture cannot be obtained for unfocused windows.
8906 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8907 mFakePolicy->assertSetPointerCaptureNotCalled();
8908 mSecondWindow->assertNoEvents();
8909
8910 // Ensure that capture can be enabled from the focus window.
8911 requestAndVerifyPointerCapture(mWindow, true);
8912
8913 // Ensure that capture cannot be disabled from a window that does not have capture.
8914 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8915 mFakePolicy->assertSetPointerCaptureNotCalled();
8916
8917 // Ensure that capture can be disabled from the window with capture.
8918 requestAndVerifyPointerCapture(mWindow, false);
8919}
8920
8921TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008922 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008923
8924 setFocusedWindow(mSecondWindow);
8925
8926 // Ensure that the capture disabled event was sent first.
8927 mWindow->consumeCaptureEvent(false);
8928 mWindow->consumeFocusEvent(false);
8929 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008930 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008931
8932 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008933 notifyPointerCaptureChanged({});
8934 notifyPointerCaptureChanged(request);
8935 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008936 mWindow->assertNoEvents();
8937 mSecondWindow->assertNoEvents();
8938 mFakePolicy->assertSetPointerCaptureNotCalled();
8939}
8940
8941TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008942 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008943
8944 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008945 notifyPointerCaptureChanged({});
8946 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008947
8948 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008949 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008950 mWindow->consumeCaptureEvent(false);
8951 mWindow->assertNoEvents();
8952}
8953
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008954TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8955 requestAndVerifyPointerCapture(mWindow, true);
8956
8957 // The first window loses focus.
8958 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008959 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008960 mWindow->consumeCaptureEvent(false);
8961
8962 // Request Pointer Capture from the second window before the notification from InputReader
8963 // arrives.
8964 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008965 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008966
8967 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008968 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008969
8970 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008971 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008972
8973 mSecondWindow->consumeFocusEvent(true);
8974 mSecondWindow->consumeCaptureEvent(true);
8975}
8976
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008977TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8978 // App repeatedly enables and disables capture.
8979 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8980 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8981 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8982 mFakePolicy->assertSetPointerCaptureCalled(false);
8983 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8984 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8985
8986 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8987 // first request is now stale, this should do nothing.
8988 notifyPointerCaptureChanged(firstRequest);
8989 mWindow->assertNoEvents();
8990
8991 // InputReader notifies that the second request was enabled.
8992 notifyPointerCaptureChanged(secondRequest);
8993 mWindow->consumeCaptureEvent(true);
8994}
8995
Prabir Pradhan7092e262022-05-03 16:51:09 +00008996TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8997 requestAndVerifyPointerCapture(mWindow, true);
8998
8999 // App toggles pointer capture off and on.
9000 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9001 mFakePolicy->assertSetPointerCaptureCalled(false);
9002
9003 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9004 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9005
9006 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9007 // preceding "disable" request.
9008 notifyPointerCaptureChanged(enableRequest);
9009
9010 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9011 // any notifications.
9012 mWindow->assertNoEvents();
9013}
9014
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009015/**
9016 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9017 * mouse movements don't affect the previous mouse hovering state.
9018 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9019 * HOVER_MOVE events).
9020 */
9021TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9022 // Mouse hover on the window
9023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9024 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9025 .build());
9026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9027 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9028 .build());
9029
9030 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9031 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9032
9033 // Start pointer capture
9034 requestAndVerifyPointerCapture(mWindow, true);
9035
9036 // Send some relative mouse movements and receive them in the window.
9037 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9038 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9039 .build());
9040 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9041 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9042
9043 // Stop pointer capture
9044 requestAndVerifyPointerCapture(mWindow, false);
9045
9046 // Continue hovering on the window
9047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9048 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9049 .build());
9050 mWindow->consumeMotionEvent(
9051 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9052
9053 mWindow->assertNoEvents();
9054}
9055
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009056class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9057protected:
9058 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009059
9060 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9061 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9062
9063 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9064 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9065
9066 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9067 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9068 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9069 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9070 MAXIMUM_OBSCURING_OPACITY);
9071
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009072 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9073 static constexpr gui::Uid APP_B_UID{10002};
9074 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009075
9076 sp<FakeWindowHandle> mTouchWindow;
9077
9078 virtual void SetUp() override {
9079 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009080 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009081 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9082 }
9083
9084 virtual void TearDown() override {
9085 InputDispatcherTest::TearDown();
9086 mTouchWindow.clear();
9087 }
9088
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009089 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009090 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009091 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009092 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009093 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009094 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009095 return window;
9096 }
9097
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009098 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009099 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9100 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009101 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009102 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009103 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009104 return window;
9105 }
9106
9107 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009108 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9109 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9110 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009111 }
9112};
9113
9114TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009115 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009116 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009117 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009118
9119 touch();
9120
9121 mTouchWindow->assertNoEvents();
9122}
9123
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009124TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009125 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9126 const sp<FakeWindowHandle>& w =
9127 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009128 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009129
9130 touch();
9131
9132 mTouchWindow->assertNoEvents();
9133}
9134
9135TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009136 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9137 const sp<FakeWindowHandle>& w =
9138 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009139 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009140
9141 touch();
9142
9143 w->assertNoEvents();
9144}
9145
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009146TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009147 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009148 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009149
9150 touch();
9151
9152 mTouchWindow->consumeAnyMotionDown();
9153}
9154
9155TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009156 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009157 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009158 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009159 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009160
9161 touch({PointF{100, 100}});
9162
9163 mTouchWindow->consumeAnyMotionDown();
9164}
9165
9166TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009167 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009168 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009169 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009170
9171 touch();
9172
9173 mTouchWindow->consumeAnyMotionDown();
9174}
9175
9176TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9177 const sp<FakeWindowHandle>& w =
9178 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009179 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009180
9181 touch();
9182
9183 mTouchWindow->consumeAnyMotionDown();
9184}
9185
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009186TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9187 const sp<FakeWindowHandle>& w =
9188 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009189 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009190
9191 touch();
9192
9193 w->assertNoEvents();
9194}
9195
9196/**
9197 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9198 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9199 * window, the occluding window will still receive ACTION_OUTSIDE event.
9200 */
9201TEST_F(InputDispatcherUntrustedTouchesTest,
9202 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9203 const sp<FakeWindowHandle>& w =
9204 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009205 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009206 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009207
9208 touch();
9209
9210 w->consumeMotionOutside();
9211}
9212
9213TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9214 const sp<FakeWindowHandle>& w =
9215 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009216 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009217 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009218
9219 touch();
9220
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009221 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009222}
9223
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009224TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009225 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009226 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9227 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009228 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009229
9230 touch();
9231
9232 mTouchWindow->consumeAnyMotionDown();
9233}
9234
9235TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9236 const sp<FakeWindowHandle>& w =
9237 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9238 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009239 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009240
9241 touch();
9242
9243 mTouchWindow->consumeAnyMotionDown();
9244}
9245
9246TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009247 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009248 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9249 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009250 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009251
9252 touch();
9253
9254 mTouchWindow->assertNoEvents();
9255}
9256
9257TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9258 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9259 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009260 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9261 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009262 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009263 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9264 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009265 mDispatcher->onWindowInfosChanged(
9266 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009267
9268 touch();
9269
9270 mTouchWindow->assertNoEvents();
9271}
9272
9273TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9274 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9275 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009276 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9277 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009278 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009279 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9280 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009281 mDispatcher->onWindowInfosChanged(
9282 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009283
9284 touch();
9285
9286 mTouchWindow->consumeAnyMotionDown();
9287}
9288
9289TEST_F(InputDispatcherUntrustedTouchesTest,
9290 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9291 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009292 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9293 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009294 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009295 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9296 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009297 mDispatcher->onWindowInfosChanged(
9298 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009299
9300 touch();
9301
9302 mTouchWindow->consumeAnyMotionDown();
9303}
9304
9305TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9306 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009307 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9308 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009309 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009310 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9311 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009312 mDispatcher->onWindowInfosChanged(
9313 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009314
9315 touch();
9316
9317 mTouchWindow->assertNoEvents();
9318}
9319
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009320TEST_F(InputDispatcherUntrustedTouchesTest,
9321 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9322 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009323 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9324 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009325 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009326 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9327 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009328 mDispatcher->onWindowInfosChanged(
9329 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009330
9331 touch();
9332
9333 mTouchWindow->assertNoEvents();
9334}
9335
9336TEST_F(InputDispatcherUntrustedTouchesTest,
9337 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9338 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009339 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9340 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009341 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009342 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9343 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009344 mDispatcher->onWindowInfosChanged(
9345 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009346
9347 touch();
9348
9349 mTouchWindow->consumeAnyMotionDown();
9350}
9351
9352TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9353 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009354 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9355 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009356 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009357
9358 touch();
9359
9360 mTouchWindow->consumeAnyMotionDown();
9361}
9362
9363TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9364 const sp<FakeWindowHandle>& w =
9365 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009366 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009367
9368 touch();
9369
9370 mTouchWindow->consumeAnyMotionDown();
9371}
9372
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009373TEST_F(InputDispatcherUntrustedTouchesTest,
9374 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9375 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9376 const sp<FakeWindowHandle>& w =
9377 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009378 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009379
9380 touch();
9381
9382 mTouchWindow->assertNoEvents();
9383}
9384
9385TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9386 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9387 const sp<FakeWindowHandle>& w =
9388 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009389 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009390
9391 touch();
9392
9393 mTouchWindow->consumeAnyMotionDown();
9394}
9395
9396TEST_F(InputDispatcherUntrustedTouchesTest,
9397 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9398 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9399 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009400 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9401 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009402 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009403
9404 touch();
9405
9406 mTouchWindow->consumeAnyMotionDown();
9407}
9408
9409TEST_F(InputDispatcherUntrustedTouchesTest,
9410 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9411 const sp<FakeWindowHandle>& w1 =
9412 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9413 OPACITY_BELOW_THRESHOLD);
9414 const sp<FakeWindowHandle>& w2 =
9415 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9416 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009417 mDispatcher->onWindowInfosChanged(
9418 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009419
9420 touch();
9421
9422 mTouchWindow->assertNoEvents();
9423}
9424
9425/**
9426 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9427 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9428 * (which alone would result in allowing touches) does not affect the blocking behavior.
9429 */
9430TEST_F(InputDispatcherUntrustedTouchesTest,
9431 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9432 const sp<FakeWindowHandle>& wB =
9433 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9434 OPACITY_BELOW_THRESHOLD);
9435 const sp<FakeWindowHandle>& wC =
9436 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9437 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009438 mDispatcher->onWindowInfosChanged(
9439 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009440
9441 touch();
9442
9443 mTouchWindow->assertNoEvents();
9444}
9445
9446/**
9447 * This test is testing that a window from a different UID but with same application token doesn't
9448 * block the touch. Apps can share the application token for close UI collaboration for example.
9449 */
9450TEST_F(InputDispatcherUntrustedTouchesTest,
9451 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9452 const sp<FakeWindowHandle>& w =
9453 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9454 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009455 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009456
9457 touch();
9458
9459 mTouchWindow->consumeAnyMotionDown();
9460}
9461
arthurhungb89ccb02020-12-30 16:19:01 +08009462class InputDispatcherDragTests : public InputDispatcherTest {
9463protected:
9464 std::shared_ptr<FakeApplicationHandle> mApp;
9465 sp<FakeWindowHandle> mWindow;
9466 sp<FakeWindowHandle> mSecondWindow;
9467 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009468 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009469 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9470 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009471
9472 void SetUp() override {
9473 InputDispatcherTest::SetUp();
9474 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009475 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009476 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009477
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009478 mSecondWindow =
9479 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009480 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009481
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009482 mSpyWindow =
9483 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009484 mSpyWindow->setSpy(true);
9485 mSpyWindow->setTrustedOverlay(true);
9486 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9487
arthurhungb89ccb02020-12-30 16:19:01 +08009488 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009489 mDispatcher->onWindowInfosChanged(
9490 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9491 {},
9492 0,
9493 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009494 }
9495
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009496 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9497 switch (fromSource) {
9498 case AINPUT_SOURCE_TOUCHSCREEN:
9499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009500 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009501 ADISPLAY_ID_DEFAULT, {50, 50}))
9502 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9503 break;
9504 case AINPUT_SOURCE_STYLUS:
9505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009506 injectMotionEvent(*mDispatcher,
9507 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9508 AINPUT_SOURCE_STYLUS)
9509 .buttonState(
9510 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9511 .pointer(PointerBuilder(0, ToolType::STYLUS)
9512 .x(50)
9513 .y(50))
9514 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009515 break;
9516 case AINPUT_SOURCE_MOUSE:
9517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009518 injectMotionEvent(*mDispatcher,
9519 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9520 AINPUT_SOURCE_MOUSE)
9521 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9522 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9523 ToolType::MOUSE)
9524 .x(50)
9525 .y(50))
9526 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009527 break;
9528 default:
9529 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9530 }
arthurhungb89ccb02020-12-30 16:19:01 +08009531
9532 // Window should receive motion event.
9533 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009534 // Spy window should also receive motion event
9535 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009536 }
9537
9538 // Start performing drag, we will create a drag window and transfer touch to it.
9539 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9540 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009541 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009542 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009543 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009544 }
arthurhungb89ccb02020-12-30 16:19:01 +08009545
9546 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009547 mDragWindow =
9548 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009549 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009550 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9551 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9552 {},
9553 0,
9554 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009555
9556 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009557 bool transferred =
9558 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009559 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009560 if (transferred) {
9561 mWindow->consumeMotionCancel();
9562 mDragWindow->consumeMotionDown();
9563 }
9564 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009565 }
9566};
9567
9568TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009569 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009570
9571 // Move on window.
9572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009573 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009574 ADISPLAY_ID_DEFAULT, {50, 50}))
9575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9576 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9577 mWindow->consumeDragEvent(false, 50, 50);
9578 mSecondWindow->assertNoEvents();
9579
9580 // Move to another window.
9581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009582 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009583 ADISPLAY_ID_DEFAULT, {150, 50}))
9584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9585 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9586 mWindow->consumeDragEvent(true, 150, 50);
9587 mSecondWindow->consumeDragEvent(false, 50, 50);
9588
9589 // Move back to original window.
9590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009591 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009592 ADISPLAY_ID_DEFAULT, {50, 50}))
9593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9594 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9595 mWindow->consumeDragEvent(false, 50, 50);
9596 mSecondWindow->consumeDragEvent(true, -50, 50);
9597
9598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009599 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9600 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009601 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9602 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9603 mWindow->assertNoEvents();
9604 mSecondWindow->assertNoEvents();
9605}
9606
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009607TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009608 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009609
9610 // No cancel event after drag start
9611 mSpyWindow->assertNoEvents();
9612
9613 const MotionEvent secondFingerDownEvent =
9614 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9615 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009616 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9617 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009618 .build();
9619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009620 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009621 InputEventInjectionSync::WAIT_FOR_RESULT))
9622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9623
9624 // Receives cancel for first pointer after next pointer down
9625 mSpyWindow->consumeMotionCancel();
9626 mSpyWindow->consumeMotionDown();
9627
9628 mSpyWindow->assertNoEvents();
9629}
9630
arthurhungf452d0b2021-01-06 00:19:52 +08009631TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009632 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009633
9634 // Move on window.
9635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009636 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009637 ADISPLAY_ID_DEFAULT, {50, 50}))
9638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9639 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9640 mWindow->consumeDragEvent(false, 50, 50);
9641 mSecondWindow->assertNoEvents();
9642
9643 // Move to another window.
9644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009645 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009646 ADISPLAY_ID_DEFAULT, {150, 50}))
9647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9648 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9649 mWindow->consumeDragEvent(true, 150, 50);
9650 mSecondWindow->consumeDragEvent(false, 50, 50);
9651
9652 // drop to another window.
9653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009654 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009655 {150, 50}))
9656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9657 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009658 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009659 mWindow->assertNoEvents();
9660 mSecondWindow->assertNoEvents();
9661}
9662
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009663TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9664 startDrag();
9665
9666 // No cancel event after drag start
9667 mSpyWindow->assertNoEvents();
9668
9669 const MotionEvent secondFingerDownEvent =
9670 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9672 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9673 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9674 .build();
9675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9676 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9677 InputEventInjectionSync::WAIT_FOR_RESULT))
9678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9679
9680 // Receives cancel for first pointer after next pointer down
9681 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9682 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9683 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9684
9685 mSpyWindow->assertNoEvents();
9686
9687 // Spy window calls pilfer pointers
9688 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9689 mDragWindow->assertNoEvents();
9690
9691 const MotionEvent firstFingerMoveEvent =
9692 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9693 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9694 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9695 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9696 .build();
9697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9698 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9699 InputEventInjectionSync::WAIT_FOR_RESULT))
9700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9701
9702 // Drag window should still receive the new event
9703 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9704 mDragWindow->assertNoEvents();
9705}
9706
arthurhung6d4bed92021-03-17 11:59:33 +08009707TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009708 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009709
9710 // Move on window and keep button pressed.
9711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009712 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009713 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9714 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009715 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009716 .build()))
9717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9718 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9719 mWindow->consumeDragEvent(false, 50, 50);
9720 mSecondWindow->assertNoEvents();
9721
9722 // Move to another window and release button, expect to drop item.
9723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009724 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009725 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9726 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009727 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009728 .build()))
9729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9730 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9731 mWindow->assertNoEvents();
9732 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009733 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009734
9735 // nothing to the window.
9736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009737 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009738 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9739 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009740 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009741 .build()))
9742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9743 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9744 mWindow->assertNoEvents();
9745 mSecondWindow->assertNoEvents();
9746}
9747
Arthur Hung54745652022-04-20 07:17:41 +00009748TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009749 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009750
9751 // Set second window invisible.
9752 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009753 mDispatcher->onWindowInfosChanged(
9754 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009755
9756 // Move on window.
9757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009758 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009759 ADISPLAY_ID_DEFAULT, {50, 50}))
9760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9761 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9762 mWindow->consumeDragEvent(false, 50, 50);
9763 mSecondWindow->assertNoEvents();
9764
9765 // Move to another window.
9766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009767 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009768 ADISPLAY_ID_DEFAULT, {150, 50}))
9769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9770 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9771 mWindow->consumeDragEvent(true, 150, 50);
9772 mSecondWindow->assertNoEvents();
9773
9774 // drop to another window.
9775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009776 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009777 {150, 50}))
9778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9779 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009780 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009781 mWindow->assertNoEvents();
9782 mSecondWindow->assertNoEvents();
9783}
9784
Arthur Hung54745652022-04-20 07:17:41 +00009785TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009786 // Ensure window could track pointerIds if it didn't support split touch.
9787 mWindow->setPreventSplitting(true);
9788
Arthur Hung54745652022-04-20 07:17:41 +00009789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009790 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009791 {50, 50}))
9792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9793 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9794
9795 const MotionEvent secondFingerDownEvent =
9796 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9797 .displayId(ADISPLAY_ID_DEFAULT)
9798 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009799 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9800 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009801 .build();
9802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009803 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009804 InputEventInjectionSync::WAIT_FOR_RESULT))
9805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009806 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009807
9808 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009809 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009810}
9811
9812TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9813 // First down on second window.
9814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009815 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009816 {150, 50}))
9817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9818
9819 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9820
9821 // Second down on first window.
9822 const MotionEvent secondFingerDownEvent =
9823 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9824 .displayId(ADISPLAY_ID_DEFAULT)
9825 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009826 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9827 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009828 .build();
9829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009830 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009831 InputEventInjectionSync::WAIT_FOR_RESULT))
9832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9833 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9834
9835 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009836 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009837
9838 // Move on window.
9839 const MotionEvent secondFingerMoveEvent =
9840 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9841 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009842 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9843 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009844 .build();
9845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009846 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009847 InputEventInjectionSync::WAIT_FOR_RESULT));
9848 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9849 mWindow->consumeDragEvent(false, 50, 50);
9850 mSecondWindow->consumeMotionMove();
9851
9852 // Release the drag pointer should perform drop.
9853 const MotionEvent secondFingerUpEvent =
9854 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9855 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009856 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9857 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009858 .build();
9859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009860 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009861 InputEventInjectionSync::WAIT_FOR_RESULT));
9862 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009863 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009864 mWindow->assertNoEvents();
9865 mSecondWindow->consumeMotionMove();
9866}
9867
Arthur Hung3915c1f2022-05-31 07:17:17 +00009868TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009869 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009870
9871 // Update window of second display.
9872 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009873 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009874 mDispatcher->onWindowInfosChanged(
9875 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9876 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9877 {},
9878 0,
9879 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009880
9881 // Let second display has a touch state.
9882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009883 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009884 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9885 AINPUT_SOURCE_TOUCHSCREEN)
9886 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009887 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009888 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009889 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009890 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009891 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009892 mDispatcher->onWindowInfosChanged(
9893 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9894 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9895 {},
9896 0,
9897 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009898
9899 // Move on window.
9900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009901 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009902 ADISPLAY_ID_DEFAULT, {50, 50}))
9903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9904 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9905 mWindow->consumeDragEvent(false, 50, 50);
9906 mSecondWindow->assertNoEvents();
9907
9908 // Move to another window.
9909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009910 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009911 ADISPLAY_ID_DEFAULT, {150, 50}))
9912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9913 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9914 mWindow->consumeDragEvent(true, 150, 50);
9915 mSecondWindow->consumeDragEvent(false, 50, 50);
9916
9917 // drop to another window.
9918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009919 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009920 {150, 50}))
9921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9922 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009923 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009924 mWindow->assertNoEvents();
9925 mSecondWindow->assertNoEvents();
9926}
9927
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009928TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9929 startDrag(true, AINPUT_SOURCE_MOUSE);
9930 // Move on window.
9931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009932 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009933 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9934 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009935 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009936 .x(50)
9937 .y(50))
9938 .build()))
9939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9940 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9941 mWindow->consumeDragEvent(false, 50, 50);
9942 mSecondWindow->assertNoEvents();
9943
9944 // Move to another window.
9945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009946 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009947 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9948 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009949 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009950 .x(150)
9951 .y(50))
9952 .build()))
9953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9954 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9955 mWindow->consumeDragEvent(true, 150, 50);
9956 mSecondWindow->consumeDragEvent(false, 50, 50);
9957
9958 // drop to another window.
9959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009960 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009961 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9962 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009963 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009964 .x(150)
9965 .y(50))
9966 .build()))
9967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9968 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009969 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009970 mWindow->assertNoEvents();
9971 mSecondWindow->assertNoEvents();
9972}
9973
Linnan Li5af92f92023-07-14 14:36:22 +08009974/**
9975 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9976 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9977 */
9978TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9979 // Down on second window
9980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9981 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9982 {150, 50}))
9983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9984
9985 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9986 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9987
9988 // Down on first window
9989 const MotionEvent secondFingerDownEvent =
9990 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9991 .displayId(ADISPLAY_ID_DEFAULT)
9992 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9993 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9994 .build();
9995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9996 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9997 InputEventInjectionSync::WAIT_FOR_RESULT))
9998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9999 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10000 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10001 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10002
10003 // Start drag on first window
10004 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10005
10006 // Trigger cancel
10007 mDispatcher->cancelCurrentTouch();
10008 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10009 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10010 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10011
10012 ASSERT_TRUE(mDispatcher->waitForIdle());
10013 // The D&D finished with nullptr
10014 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10015
10016 // Remove drag window
10017 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10018
10019 // Inject a simple gesture, ensure dispatcher not crashed
10020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10021 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10022 PointF{50, 50}))
10023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10024 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10025
10026 const MotionEvent moveEvent =
10027 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10028 .displayId(ADISPLAY_ID_DEFAULT)
10029 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10030 .build();
10031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10032 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10033 InputEventInjectionSync::WAIT_FOR_RESULT))
10034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10035 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10036
10037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10038 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10039 {50, 50}))
10040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10041 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10042}
10043
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010044TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10045 // Start hovering over the window.
10046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10047 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10048 ADISPLAY_ID_DEFAULT, {50, 50}));
10049
10050 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10051 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10052
10053 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10054 << "Drag and drop should not work with a hovering pointer";
10055}
10056
Vishnu Nair062a8672021-09-03 16:07:44 -070010057class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10058
10059TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010061 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10062 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010063 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010064 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10065 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010067 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010068 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010069
10070 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010071 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010072 window->assertNoEvents();
10073
Prabir Pradhan678438e2023-04-13 19:32:51 +000010074 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10075 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010076 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10077 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010078 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010079 window->assertNoEvents();
10080
10081 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010082 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010083 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010084
Prabir Pradhan678438e2023-04-13 19:32:51 +000010085 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010086 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10087
Prabir Pradhan678438e2023-04-13 19:32:51 +000010088 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10089 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010090 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10091 window->assertNoEvents();
10092}
10093
10094TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10095 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10096 std::make_shared<FakeApplicationHandle>();
10097 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010098 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10099 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010100 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010101 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010102 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010103 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010104 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10105 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010106 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010107 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010108 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10109 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010110 mDispatcher->onWindowInfosChanged(
10111 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010112 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010113 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010114
10115 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010116 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010117 window->assertNoEvents();
10118
Prabir Pradhan678438e2023-04-13 19:32:51 +000010119 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10120 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010121 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10122 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010123 window->assertNoEvents();
10124
10125 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010126 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010127 mDispatcher->onWindowInfosChanged(
10128 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010129
Prabir Pradhan678438e2023-04-13 19:32:51 +000010130 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010131 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10132
Prabir Pradhan678438e2023-04-13 19:32:51 +000010133 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10134 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010135 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10136 window->assertNoEvents();
10137}
10138
10139TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10140 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10141 std::make_shared<FakeApplicationHandle>();
10142 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010143 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10144 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010145 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010146 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010147 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010149 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10150 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010151 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010152 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010153 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10154 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010155 mDispatcher->onWindowInfosChanged(
10156 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010157 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010158 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010159
10160 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010161 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010162 window->assertNoEvents();
10163
Prabir Pradhan678438e2023-04-13 19:32:51 +000010164 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10165 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10167 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010168 window->assertNoEvents();
10169
10170 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010171 mDispatcher->onWindowInfosChanged(
10172 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010173
Prabir Pradhan678438e2023-04-13 19:32:51 +000010174 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010175 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10176
Prabir Pradhan678438e2023-04-13 19:32:51 +000010177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010179 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10180 window->assertNoEvents();
10181}
10182
Antonio Kantekf16f2832021-09-28 04:39:20 +000010183class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10184protected:
10185 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010186 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010187 sp<FakeWindowHandle> mWindow;
10188 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010189 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010190
10191 void SetUp() override {
10192 InputDispatcherTest::SetUp();
10193
10194 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010195 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010196 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010197 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010198 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010199 mSecondWindow =
10200 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010201 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010202 mThirdWindow =
10203 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10204 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10205 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010206
10207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010208 mDispatcher->onWindowInfosChanged(
10209 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10210 {},
10211 0,
10212 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010213 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010214 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010215
Antonio Kantek15beb512022-06-13 22:35:41 +000010216 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010217 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010218 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010219 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10220 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010221 mThirdWindow->assertNoEvents();
10222 }
10223
10224 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10225 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010226 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010227 SECOND_DISPLAY_ID)) {
10228 mWindow->assertNoEvents();
10229 mSecondWindow->assertNoEvents();
10230 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010231 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010232 }
10233
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010234 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010235 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010236 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10237 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010238 mWindow->consumeTouchModeEvent(inTouchMode);
10239 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010240 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010241 }
10242};
10243
Antonio Kantek26defcf2022-02-08 01:12:27 +000010244TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010245 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010246 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10247 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010248 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010249}
10250
Antonio Kantek26defcf2022-02-08 01:12:27 +000010251TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10252 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010253 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010254 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010255 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010256 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010257 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010258 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010259 mWindow->assertNoEvents();
10260 mSecondWindow->assertNoEvents();
10261}
10262
10263TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10264 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010265 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010266 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010267 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010268 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010269 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010270}
10271
Antonio Kantekf16f2832021-09-28 04:39:20 +000010272TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010273 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010274 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10275 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010276 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010277 mWindow->assertNoEvents();
10278 mSecondWindow->assertNoEvents();
10279}
10280
Antonio Kantek15beb512022-06-13 22:35:41 +000010281TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10282 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10283 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10284 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010285 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010286 mWindow->assertNoEvents();
10287 mSecondWindow->assertNoEvents();
10288 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10289}
10290
Antonio Kantek48710e42022-03-24 14:19:30 -070010291TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10292 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10294 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010295 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10296 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10297
10298 // Then remove focus.
10299 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010300 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010301
10302 // Assert that caller can switch touch mode by owning one of the last interacted window.
10303 const WindowInfo& windowInfo = *mWindow->getInfo();
10304 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10305 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010306 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010307}
10308
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010309class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10310public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010311 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010312 std::shared_ptr<FakeApplicationHandle> application =
10313 std::make_shared<FakeApplicationHandle>();
10314 std::string name = "Fake Spy ";
10315 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010316 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10317 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010318 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010319 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010320 return spy;
10321 }
10322
10323 sp<FakeWindowHandle> createForeground() {
10324 std::shared_ptr<FakeApplicationHandle> application =
10325 std::make_shared<FakeApplicationHandle>();
10326 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010327 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10328 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010329 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010330 return window;
10331 }
10332
10333private:
10334 int mSpyCount{0};
10335};
10336
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010337using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010338/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010339 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10340 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010341TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010342 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010343 ScopedSilentDeath _silentDeath;
10344
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010345 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010346 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010347 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010348 ".* not a trusted overlay");
10349}
10350
10351/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010352 * Input injection into a display with a spy window but no foreground windows should succeed.
10353 */
10354TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010355 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010356 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010357
10358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010359 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10361 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10362}
10363
10364/**
10365 * Verify the order in which different input windows receive events. The touched foreground window
10366 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10367 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10368 * receive events before ones belows it.
10369 *
10370 * Here, we set up a scenario with four windows in the following Z order from the top:
10371 * spy1, spy2, window, spy3.
10372 * We then inject an event and verify that the foreground "window" receives it first, followed by
10373 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10374 * window.
10375 */
10376TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10377 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010378 auto spy1 = createSpy();
10379 auto spy2 = createSpy();
10380 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010381 mDispatcher->onWindowInfosChanged(
10382 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010383 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10384 const size_t numChannels = channels.size();
10385
Michael Wright8e9a8562022-02-09 13:44:29 +000010386 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010387 if (!epollFd.ok()) {
10388 FAIL() << "Failed to create epoll fd";
10389 }
10390
10391 for (size_t i = 0; i < numChannels; i++) {
10392 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10393 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10394 FAIL() << "Failed to add fd to epoll";
10395 }
10396 }
10397
10398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010399 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010400 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10401
10402 std::vector<size_t> eventOrder;
10403 std::vector<struct epoll_event> events(numChannels);
10404 for (;;) {
10405 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10406 (100ms).count());
10407 if (nFds < 0) {
10408 FAIL() << "Failed to call epoll_wait";
10409 }
10410 if (nFds == 0) {
10411 break; // epoll_wait timed out
10412 }
10413 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010414 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010415 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010416 channels[i]->consumeMotionDown();
10417 }
10418 }
10419
10420 // Verify the order in which the events were received.
10421 EXPECT_EQ(3u, eventOrder.size());
10422 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10423 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10424 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10425}
10426
10427/**
10428 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10429 */
10430TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10431 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010432 auto spy = createSpy();
10433 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010434 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010435
10436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010437 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10439 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10440 spy->assertNoEvents();
10441}
10442
10443/**
10444 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10445 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10446 * to the window.
10447 */
10448TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10449 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010450 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010451 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010452 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010453
10454 // Inject an event outside the spy window's touchable region.
10455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010456 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10458 window->consumeMotionDown();
10459 spy->assertNoEvents();
10460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010461 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10463 window->consumeMotionUp();
10464 spy->assertNoEvents();
10465
10466 // Inject an event inside the spy window's touchable region.
10467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010469 {5, 10}))
10470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10471 window->consumeMotionDown();
10472 spy->consumeMotionDown();
10473}
10474
10475/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010476 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010477 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010478 */
10479TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10480 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010481 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010482 auto spy = createSpy();
10483 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010484 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010485 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010486 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010487
10488 // Inject an event outside the spy window's frame and touchable region.
10489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010490 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010491 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010492 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10493 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010494 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010495}
10496
10497/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010498 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10499 * pointers that are down within its bounds.
10500 */
10501TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10502 auto windowLeft = createForeground();
10503 windowLeft->setFrame({0, 0, 100, 200});
10504 auto windowRight = createForeground();
10505 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010506 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010507 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010508 mDispatcher->onWindowInfosChanged(
10509 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010510
10511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010512 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010513 {50, 50}))
10514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10515 windowLeft->consumeMotionDown();
10516 spy->consumeMotionDown();
10517
10518 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010519 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010520 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010521 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10522 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010523 .build();
10524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010525 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010526 InputEventInjectionSync::WAIT_FOR_RESULT))
10527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10528 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010529 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010530}
10531
10532/**
10533 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10534 * the spy should receive the second pointer with ACTION_DOWN.
10535 */
10536TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10537 auto window = createForeground();
10538 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010539 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010540 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010541 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010542
10543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010545 {50, 50}))
10546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10547 window->consumeMotionDown();
10548 spyRight->assertNoEvents();
10549
10550 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010551 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010552 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010553 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10554 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010555 .build();
10556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010557 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010558 InputEventInjectionSync::WAIT_FOR_RESULT))
10559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010560 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010561 spyRight->consumeMotionDown();
10562}
10563
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010564/**
10565 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10566 * windows should be allowed to control split touch.
10567 */
10568TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010569 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010570 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010571 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010572 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010573
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010574 auto window = createForeground();
10575 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010576
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010577 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010578
10579 // First finger down, no window touched.
10580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010581 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010582 {100, 200}))
10583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10584 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10585 window->assertNoEvents();
10586
10587 // Second finger down on window, the window should receive touch down.
10588 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010589 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010590 .displayId(ADISPLAY_ID_DEFAULT)
10591 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010592 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10593 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010594 .build();
10595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010596 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010597 InputEventInjectionSync::WAIT_FOR_RESULT))
10598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10599
10600 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010601 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010602}
10603
10604/**
10605 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10606 * do not receive key events.
10607 */
10608TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010609 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010610 spy->setFocusable(false);
10611
10612 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010613 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010614 setFocusedWindow(window);
10615 window->consumeFocusEvent(true);
10616
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010618 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10619 window->consumeKeyDown(ADISPLAY_ID_NONE);
10620
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010622 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10623 window->consumeKeyUp(ADISPLAY_ID_NONE);
10624
10625 spy->assertNoEvents();
10626}
10627
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010628using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10629
10630/**
10631 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10632 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10633 */
10634TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10635 auto window = createForeground();
10636 auto spy1 = createSpy();
10637 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010638 mDispatcher->onWindowInfosChanged(
10639 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010640
10641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010642 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10644 window->consumeMotionDown();
10645 spy1->consumeMotionDown();
10646 spy2->consumeMotionDown();
10647
10648 // Pilfer pointers from the second spy window.
10649 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10650 spy2->assertNoEvents();
10651 spy1->consumeMotionCancel();
10652 window->consumeMotionCancel();
10653
10654 // The rest of the gesture should only be sent to the second spy window.
10655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010656 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010657 ADISPLAY_ID_DEFAULT))
10658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10659 spy2->consumeMotionMove();
10660 spy1->assertNoEvents();
10661 window->assertNoEvents();
10662}
10663
10664/**
10665 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10666 * in the middle of the gesture.
10667 */
10668TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10669 auto window = createForeground();
10670 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010671 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010672
10673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010674 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10676 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10677 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10678
10679 window->releaseChannel();
10680
10681 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10682
10683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010684 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10686 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10687}
10688
10689/**
10690 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10691 * the spy, but not to any other windows.
10692 */
10693TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10694 auto spy = createSpy();
10695 auto window = createForeground();
10696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010697 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010698
10699 // First finger down on the window and the spy.
10700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010701 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010702 {100, 200}))
10703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10704 spy->consumeMotionDown();
10705 window->consumeMotionDown();
10706
10707 // Spy window pilfers the pointers.
10708 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10709 window->consumeMotionCancel();
10710
10711 // Second finger down on the window and spy, but the window should not receive the pointer down.
10712 const MotionEvent secondFingerDownEvent =
10713 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10714 .displayId(ADISPLAY_ID_DEFAULT)
10715 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010716 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10717 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010718 .build();
10719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010720 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010721 InputEventInjectionSync::WAIT_FOR_RESULT))
10722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10723
Harry Cutts33476232023-01-30 19:57:29 +000010724 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010725
10726 // Third finger goes down outside all windows, so injection should fail.
10727 const MotionEvent thirdFingerDownEvent =
10728 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10729 .displayId(ADISPLAY_ID_DEFAULT)
10730 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010731 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10732 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10733 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010734 .build();
10735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010736 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010737 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010738 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010739
10740 spy->assertNoEvents();
10741 window->assertNoEvents();
10742}
10743
10744/**
10745 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10746 */
10747TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10748 auto spy = createSpy();
10749 spy->setFrame(Rect(0, 0, 100, 100));
10750 auto window = createForeground();
10751 window->setFrame(Rect(0, 0, 200, 200));
10752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010753 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010754
10755 // First finger down on the window only
10756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010757 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010758 {150, 150}))
10759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10760 window->consumeMotionDown();
10761
10762 // Second finger down on the spy and window
10763 const MotionEvent secondFingerDownEvent =
10764 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10765 .displayId(ADISPLAY_ID_DEFAULT)
10766 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010767 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10768 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010769 .build();
10770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010771 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010772 InputEventInjectionSync::WAIT_FOR_RESULT))
10773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10774 spy->consumeMotionDown();
10775 window->consumeMotionPointerDown(1);
10776
10777 // Third finger down on the spy and window
10778 const MotionEvent thirdFingerDownEvent =
10779 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10780 .displayId(ADISPLAY_ID_DEFAULT)
10781 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010782 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10783 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10784 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010785 .build();
10786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010787 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010788 InputEventInjectionSync::WAIT_FOR_RESULT))
10789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10790 spy->consumeMotionPointerDown(1);
10791 window->consumeMotionPointerDown(2);
10792
10793 // Spy window pilfers the pointers.
10794 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010795 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10796 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010797
10798 spy->assertNoEvents();
10799 window->assertNoEvents();
10800}
10801
10802/**
10803 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10804 * other windows should be canceled. If this results in the cancellation of all pointers for some
10805 * window, then that window should receive ACTION_CANCEL.
10806 */
10807TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10808 auto spy = createSpy();
10809 spy->setFrame(Rect(0, 0, 100, 100));
10810 auto window = createForeground();
10811 window->setFrame(Rect(0, 0, 200, 200));
10812
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010813 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010814
10815 // First finger down on both spy and window
10816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010817 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010818 {10, 10}))
10819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10820 window->consumeMotionDown();
10821 spy->consumeMotionDown();
10822
10823 // Second finger down on the spy and window
10824 const MotionEvent secondFingerDownEvent =
10825 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10826 .displayId(ADISPLAY_ID_DEFAULT)
10827 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010828 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10829 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010830 .build();
10831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010832 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010833 InputEventInjectionSync::WAIT_FOR_RESULT))
10834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10835 spy->consumeMotionPointerDown(1);
10836 window->consumeMotionPointerDown(1);
10837
10838 // Spy window pilfers the pointers.
10839 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10840 window->consumeMotionCancel();
10841
10842 spy->assertNoEvents();
10843 window->assertNoEvents();
10844}
10845
10846/**
10847 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10848 * be sent to other windows
10849 */
10850TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10851 auto spy = createSpy();
10852 spy->setFrame(Rect(0, 0, 100, 100));
10853 auto window = createForeground();
10854 window->setFrame(Rect(0, 0, 200, 200));
10855
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010856 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010857
10858 // First finger down on both window and spy
10859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010860 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010861 {10, 10}))
10862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10863 window->consumeMotionDown();
10864 spy->consumeMotionDown();
10865
10866 // Spy window pilfers the pointers.
10867 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10868 window->consumeMotionCancel();
10869
10870 // Second finger down on the window only
10871 const MotionEvent secondFingerDownEvent =
10872 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10873 .displayId(ADISPLAY_ID_DEFAULT)
10874 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010875 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10876 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010877 .build();
10878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010879 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010880 InputEventInjectionSync::WAIT_FOR_RESULT))
10881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10882 window->consumeMotionDown();
10883 window->assertNoEvents();
10884
10885 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10886 spy->consumeMotionMove();
10887 spy->assertNoEvents();
10888}
10889
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010890/**
10891 * A window on the left and a window on the right. Also, a spy window that's above all of the
10892 * windows, and spanning both left and right windows.
10893 * Send simultaneous motion streams from two different devices, one to the left window, and another
10894 * to the right window.
10895 * Pilfer from spy window.
10896 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10897 */
10898TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10899 sp<FakeWindowHandle> spy = createSpy();
10900 spy->setFrame(Rect(0, 0, 200, 200));
10901 sp<FakeWindowHandle> leftWindow = createForeground();
10902 leftWindow->setFrame(Rect(0, 0, 100, 100));
10903
10904 sp<FakeWindowHandle> rightWindow = createForeground();
10905 rightWindow->setFrame(Rect(100, 0, 200, 100));
10906
10907 constexpr int32_t stylusDeviceId = 1;
10908 constexpr int32_t touchDeviceId = 2;
10909
10910 mDispatcher->onWindowInfosChanged(
10911 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10912
10913 // Stylus down on left window and spy
10914 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10915 .deviceId(stylusDeviceId)
10916 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10917 .build());
10918 leftWindow->consumeMotionEvent(
10919 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10920 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10921
10922 // Finger down on right window and spy - but spy already has stylus
10923 mDispatcher->notifyMotion(
10924 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10925 .deviceId(touchDeviceId)
10926 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10927 .build());
10928 rightWindow->consumeMotionEvent(
10929 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010930 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010931
10932 // Act: pilfer from spy. Spy is currently receiving touch events.
10933 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010934 leftWindow->consumeMotionEvent(
10935 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010936 rightWindow->consumeMotionEvent(
10937 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10938
10939 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10940 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10941 .deviceId(stylusDeviceId)
10942 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10943 .build());
10944 mDispatcher->notifyMotion(
10945 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10946 .deviceId(touchDeviceId)
10947 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10948 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010949 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010950
10951 spy->assertNoEvents();
10952 leftWindow->assertNoEvents();
10953 rightWindow->assertNoEvents();
10954}
10955
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010956TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
10957 auto window = createForeground();
10958 auto spy = createSpy();
10959 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
10960
10961 mDispatcher->notifyMotion(
10962 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10963 .deviceId(1)
10964 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
10965 .build());
10966 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10967 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10968
10969 // Pilfer pointers from the spy window should fail.
10970 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
10971 spy->assertNoEvents();
10972 window->assertNoEvents();
10973}
10974
Prabir Pradhand65552b2021-10-07 11:23:50 -070010975class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10976public:
10977 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10978 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10979 std::make_shared<FakeApplicationHandle>();
10980 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010981 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10982 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010983 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010984 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010985 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010986 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010987 overlay->setTrustedOverlay(true);
10988
10989 std::shared_ptr<FakeApplicationHandle> application =
10990 std::make_shared<FakeApplicationHandle>();
10991 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010992 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10993 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010994 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010995 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010996
10997 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010998 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010999 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011000 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011001 return {std::move(overlay), std::move(window)};
11002 }
11003
11004 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011005 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011006 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011007 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011008 }
11009
11010 void sendStylusEvent(int32_t action) {
11011 NotifyMotionArgs motionArgs =
11012 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11013 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011014 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011015 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011016 }
11017};
11018
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011019using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11020
11021TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011022 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011023 ScopedSilentDeath _silentDeath;
11024
Prabir Pradhand65552b2021-10-07 11:23:50 -070011025 auto [overlay, window] = setupStylusOverlayScenario();
11026 overlay->setTrustedOverlay(false);
11027 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011028 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11029 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011030 ".* not a trusted overlay");
11031}
11032
11033TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11034 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011035 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011036
11037 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11038 overlay->consumeMotionDown();
11039 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11040 overlay->consumeMotionUp();
11041
11042 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11043 window->consumeMotionDown();
11044 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11045 window->consumeMotionUp();
11046
11047 overlay->assertNoEvents();
11048 window->assertNoEvents();
11049}
11050
11051TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11052 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011053 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011054 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011055
11056 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11057 overlay->consumeMotionDown();
11058 window->consumeMotionDown();
11059 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11060 overlay->consumeMotionUp();
11061 window->consumeMotionUp();
11062
11063 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11064 window->consumeMotionDown();
11065 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11066 window->consumeMotionUp();
11067
11068 overlay->assertNoEvents();
11069 window->assertNoEvents();
11070}
11071
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011072/**
11073 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11074 * The scenario is as follows:
11075 * - The stylus interceptor overlay is configured as a spy window.
11076 * - The stylus interceptor spy receives the start of a new stylus gesture.
11077 * - It pilfers pointers and then configures itself to no longer be a spy.
11078 * - The stylus interceptor continues to receive the rest of the gesture.
11079 */
11080TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11081 auto [overlay, window] = setupStylusOverlayScenario();
11082 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011083 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011084
11085 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11086 overlay->consumeMotionDown();
11087 window->consumeMotionDown();
11088
11089 // The interceptor pilfers the pointers.
11090 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11091 window->consumeMotionCancel();
11092
11093 // The interceptor configures itself so that it is no longer a spy.
11094 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011095 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011096
11097 // It continues to receive the rest of the stylus gesture.
11098 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11099 overlay->consumeMotionMove();
11100 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11101 overlay->consumeMotionUp();
11102
11103 window->assertNoEvents();
11104}
11105
Prabir Pradhan5735a322022-04-11 17:23:34 +000011106struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011107 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011108 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011109 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11110 std::unique_ptr<InputDispatcher>& mDispatcher;
11111
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011112 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011113 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11114
11115 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011116 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011117 ADISPLAY_ID_DEFAULT, {100, 200},
11118 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11119 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11120 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11121 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11122 }
11123
11124 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011125 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011126 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011127 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011128 mPolicyFlags);
11129 }
11130
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011131 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011132 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11133 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011134 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11135 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011136 window->setOwnerInfo(mPid, mUid);
11137 return window;
11138 }
11139};
11140
11141using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11142
11143TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011144 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011145 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011147
11148 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11149 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11150 window->consumeMotionDown();
11151
11152 setFocusedWindow(window);
11153 window->consumeFocusEvent(true);
11154
11155 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11156 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11157 window->consumeKeyDown(ADISPLAY_ID_NONE);
11158}
11159
11160TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011161 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011162 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011163 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011164
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011165 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011166 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11167 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11168
11169 setFocusedWindow(window);
11170 window->consumeFocusEvent(true);
11171
11172 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11173 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11174 window->assertNoEvents();
11175}
11176
11177TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011178 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011179 auto window = owner.createWindow("Owned window");
11180 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011181 spy->setSpy(true);
11182 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011183 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011184
11185 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11186 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11187 spy->consumeMotionDown();
11188 window->consumeMotionDown();
11189}
11190
11191TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011192 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011193 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011194
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011195 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011196 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011197 randosSpy->setSpy(true);
11198 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011199 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011200
11201 // The event is targeted at owner's window, so injection should succeed, but the spy should
11202 // not receive the event.
11203 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11204 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11205 randosSpy->assertNoEvents();
11206 window->consumeMotionDown();
11207}
11208
11209TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011210 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011211 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011212
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011213 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011214 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011215 randosSpy->setSpy(true);
11216 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011217 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011218
11219 // A user that has injection permission can inject into any window.
11220 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011221 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011222 ADISPLAY_ID_DEFAULT));
11223 randosSpy->consumeMotionDown();
11224 window->consumeMotionDown();
11225
11226 setFocusedWindow(randosSpy);
11227 randosSpy->consumeFocusEvent(true);
11228
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011229 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011230 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11231 window->assertNoEvents();
11232}
11233
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011234TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011235 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011236 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011237
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011238 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011239 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011240 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11241 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011242 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011243
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011244 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011245 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11246 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11247 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011248 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011249}
11250
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011251using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11252
11253TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11254 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11255
11256 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11257 ADISPLAY_ID_DEFAULT);
11258 left->setFrame(Rect(0, 0, 100, 100));
11259 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11260 "Right Window", ADISPLAY_ID_DEFAULT);
11261 right->setFrame(Rect(100, 0, 200, 100));
11262 sp<FakeWindowHandle> spy =
11263 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11264 spy->setFrame(Rect(0, 0, 200, 100));
11265 spy->setTrustedOverlay(true);
11266 spy->setSpy(true);
11267
11268 mDispatcher->onWindowInfosChanged(
11269 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11270
11271 // Hover into the left window.
11272 mDispatcher->notifyMotion(
11273 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11274 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11275 .build());
11276
11277 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11278 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11279
11280 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11281 /*pointerId=*/0));
11282 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11283 /*pointerId=*/0));
11284 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11285 /*pointerId=*/0));
11286
11287 // Hover move to the right window.
11288 mDispatcher->notifyMotion(
11289 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11290 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11291 .build());
11292
11293 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11294 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11295 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11296
11297 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11298 /*pointerId=*/0));
11299 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11300 /*pointerId=*/0));
11301 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11302 /*pointerId=*/0));
11303
11304 // Stop hovering.
11305 mDispatcher->notifyMotion(
11306 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11307 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11308 .build());
11309
11310 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11311 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11312
11313 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11314 /*pointerId=*/0));
11315 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11316 /*pointerId=*/0));
11317 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11318 /*pointerId=*/0));
11319}
11320
11321TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11322 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11323
11324 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11325 ADISPLAY_ID_DEFAULT);
11326 left->setFrame(Rect(0, 0, 100, 100));
11327 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11328 "Right Window", ADISPLAY_ID_DEFAULT);
11329 right->setFrame(Rect(100, 0, 200, 100));
11330 sp<FakeWindowHandle> spy =
11331 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11332 spy->setFrame(Rect(0, 0, 200, 100));
11333 spy->setTrustedOverlay(true);
11334 spy->setSpy(true);
11335
11336 mDispatcher->onWindowInfosChanged(
11337 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11338
11339 // First pointer down on left window.
11340 mDispatcher->notifyMotion(
11341 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11342 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11343 .build());
11344
11345 left->consumeMotionDown();
11346 spy->consumeMotionDown();
11347
11348 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11349 /*pointerId=*/0));
11350 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11351 /*pointerId=*/0));
11352 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11353 /*pointerId=*/0));
11354
11355 // Second pointer down on right window.
11356 mDispatcher->notifyMotion(
11357 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11358 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11359 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11360 .build());
11361
11362 left->consumeMotionMove();
11363 right->consumeMotionDown();
11364 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11365
11366 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11367 /*pointerId=*/0));
11368 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11369 /*pointerId=*/0));
11370 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11371 /*pointerId=*/0));
11372 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11373 /*pointerId=*/1));
11374 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11375 /*pointerId=*/1));
11376 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11377 /*pointerId=*/1));
11378
11379 // Second pointer up.
11380 mDispatcher->notifyMotion(
11381 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11382 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11383 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11384 .build());
11385
11386 left->consumeMotionMove();
11387 right->consumeMotionUp();
11388 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11389
11390 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11391 /*pointerId=*/0));
11392 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11393 /*pointerId=*/0));
11394 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11395 /*pointerId=*/0));
11396 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11397 /*pointerId=*/1));
11398 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11399 /*pointerId=*/1));
11400 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11401 /*pointerId=*/1));
11402
11403 // First pointer up.
11404 mDispatcher->notifyMotion(
11405 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11406 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11407 .build());
11408
11409 left->consumeMotionUp();
11410 spy->consumeMotionUp();
11411
11412 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11413 /*pointerId=*/0));
11414 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11415 /*pointerId=*/0));
11416 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11417 /*pointerId=*/0));
11418}
11419
11420TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11422
11423 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11424 ADISPLAY_ID_DEFAULT);
11425 left->setFrame(Rect(0, 0, 100, 100));
11426 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11427 "Right Window", ADISPLAY_ID_DEFAULT);
11428 right->setFrame(Rect(100, 0, 200, 100));
11429
11430 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11431
11432 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11433 /*pointerId=*/0));
11434 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11435 /*pointerId=*/0));
11436
11437 // Hover move into the window.
11438 mDispatcher->notifyMotion(
11439 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11440 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11441 .rawXCursorPosition(50)
11442 .rawYCursorPosition(50)
11443 .deviceId(DEVICE_ID)
11444 .build());
11445
11446 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11447
11448 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11449 /*pointerId=*/0));
11450
11451 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11452 mDispatcher->notifyMotion(
11453 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11454 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11455 .rawXCursorPosition(51)
11456 .rawYCursorPosition(50)
11457 .deviceId(SECOND_DEVICE_ID)
11458 .build());
11459
11460 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11461 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11462
11463 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11464 // a HOVER_EXIT from the first device.
11465 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11466 /*pointerId=*/0));
11467 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11468 SECOND_DEVICE_ID,
11469 /*pointerId=*/0));
11470
11471 // Move the mouse outside the window. Document the current behavior, where the window does not
11472 // receive HOVER_EXIT even though the mouse left the window.
11473 mDispatcher->notifyMotion(
11474 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11475 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11476 .rawXCursorPosition(150)
11477 .rawYCursorPosition(50)
11478 .deviceId(SECOND_DEVICE_ID)
11479 .build());
11480
11481 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11482 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11483 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11484 /*pointerId=*/0));
11485 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11486 SECOND_DEVICE_ID,
11487 /*pointerId=*/0));
11488}
11489
Garfield Tane84e6f92019-08-29 17:28:41 -070011490} // namespace android::inputdispatcher