blob: e18445070df1591f36f32982376f474eafa09045 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000575 mLastNotifySwitch =
576 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 }
578
Josep del Riob3981622023-04-18 15:49:45 +0000579 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
580 std::scoped_lock lock(mLock);
581 mPokedUserActivity = true;
582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700584 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
585 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700590 mOnPointerDownToken = newToken;
591 }
592
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000593 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800594 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 mPointerCaptureChangedCondition.notify_all();
597 }
598
arthurhungf452d0b2021-01-06 00:19:52 +0800599 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
600 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800601 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800602 mDropTargetWindowToken = token;
603 }
604
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000605 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000606 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000607 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
608 }
609
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700610 void assertFilterInputEventWasCalledInternal(
611 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800613 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700614 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800615 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800616 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700618} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620// --- InputDispatcherTest ---
621
622class InputDispatcherTest : public testing::Test {
623protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700625 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000627 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000628 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700629 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
630
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000712 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000783 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000840 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
841 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000842 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000843 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844
845 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
846 args.policyFlags |= POLICY_FLAG_TRUSTED;
847 mFakePolicy->assertNotifySwitchWasCalled(args);
848}
849
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700850namespace {
851
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800859class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860public:
Garfield Tan15601662020-09-22 15:32:38 -0700861 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700862 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800863
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000864 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 if (!consumeSeq) {
868 return nullptr;
869 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000870 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 return event;
872 }
873
874 /**
875 * Receive an event without acknowledging it.
876 * Return the sequence number that could later be used to send finished signal.
877 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700878 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
879 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 uint32_t consumeSeq;
881 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 std::chrono::time_point start = std::chrono::steady_clock::now();
884 status_t status = WOULD_BLOCK;
885 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700886 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
887 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700889 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 break;
891 }
892 }
893
894 if (status == WOULD_BLOCK) {
895 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800897 }
898
899 if (status != OK) {
900 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
903 if (event == nullptr) {
904 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700907 if (outEvent != nullptr) {
908 *outEvent = event;
909 }
910 return consumeSeq;
911 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913 /**
914 * To be used together with "receiveEvent" to complete the consumption of an event.
915 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000916 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700917 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700918 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800919 }
920
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700922 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000923 ASSERT_EQ(OK, status);
924 }
925
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000927 std::optional<int32_t> expectedDisplayId,
928 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700929 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
931 ASSERT_NE(nullptr, event) << mName.c_str()
932 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800933 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
935 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800936
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedDisplayId.has_value()) {
938 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940
Tiger Huang8664f8c2018-10-11 19:14:35 +0800941 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800943 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700944 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 if (expectedFlags.has_value()) {
946 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
947 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800948 break;
949 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700950 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800951 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700952 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000953 if (expectedFlags.has_value()) {
954 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
955 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956 break;
957 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100959 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700961 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800962 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000965 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800968 FAIL() << "Use 'consumeDragEvent' for DRAG events";
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 }
972
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700974 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800975
976 if (event == nullptr) {
977 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
978 return nullptr;
979 }
980
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 if (event->getType() != InputEventType::MOTION) {
982 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 return nullptr;
984 }
985 return static_cast<MotionEvent*>(event);
986 }
987
988 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
989 MotionEvent* motionEvent = consumeMotion();
990 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
991 ASSERT_THAT(*motionEvent, matcher);
992 }
993
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700995 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996 ASSERT_NE(nullptr, event) << mName.c_str()
997 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 ASSERT_EQ(InputEventType::FOCUS, event->getType())
999 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000
1001 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1002 << mName.c_str() << ": event displayId should always be NONE.";
1003
1004 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1005 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006 }
1007
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001009 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 ASSERT_NE(nullptr, event) << mName.c_str()
1011 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1013 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001014
1015 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1016 << mName.c_str() << ": event displayId should always be NONE.";
1017
1018 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1019 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1020 }
1021
arthurhungb89ccb02020-12-30 16:19:01 +08001022 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001023 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001024 ASSERT_NE(nullptr, event) << mName.c_str()
1025 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001026 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001027
1028 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030
1031 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1032 EXPECT_EQ(isExiting, dragEvent.isExiting());
1033 EXPECT_EQ(x, dragEvent.getX());
1034 EXPECT_EQ(y, dragEvent.getY());
1035 }
1036
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001038 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1042 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1047 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1048 }
1049
chaviwd1c23182019-12-20 18:44:56 -08001050 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001051 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 if (event == nullptr) {
1053 return;
1054 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001057 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001060 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1063 ADD_FAILURE() << "Received focus event, hasFocus = "
1064 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001066 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1067 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1068 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1071 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1072 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 }
1074 FAIL() << mName.c_str()
1075 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001076 }
1077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001081
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001082private:
1083 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001084 PreallocatedInputEventFactory mEventFactory;
1085
1086 std::string mName;
1087};
1088
chaviw3277faf2021-05-19 16:45:23 -05001089class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001090public:
1091 static const int32_t WIDTH = 600;
1092 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001093
Chris Yea209fde2020-07-22 13:54:51 -07001094 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001095 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001098 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001099 base::Result<std::unique_ptr<InputChannel>> channel =
1100 dispatcher->createInputChannel(name);
1101 token = (*channel)->getConnectionToken();
1102 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001103 }
1104
1105 inputApplicationHandle->updateInfo();
1106 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1107
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001108 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001109 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001110 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001111 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001112 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001113 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001114 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001115 mInfo.globalScaleFactor = 1.0;
1116 mInfo.touchableRegion.clear();
1117 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001118 mInfo.ownerPid = WINDOW_PID;
1119 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001120 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001121 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001124 sp<FakeWindowHandle> clone(int32_t displayId) {
1125 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1126 handle->mInfo = mInfo;
1127 handle->mInfo.displayId = displayId;
1128 handle->mInfo.id = sId++;
1129 handle->mInputReceiver = mInputReceiver;
1130 return handle;
1131 }
1132
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001133 void setTouchable(bool touchable) {
1134 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1135 }
chaviwd1c23182019-12-20 18:44:56 -08001136
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001137 void setFocusable(bool focusable) {
1138 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1139 }
1140
1141 void setVisible(bool visible) {
1142 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1143 }
Vishnu Nair958da932020-08-21 17:12:37 -07001144
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001146 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001147 }
1148
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001149 void setPaused(bool paused) {
1150 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1151 }
1152
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001153 void setPreventSplitting(bool preventSplitting) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 }
1156
1157 void setSlippery(bool slippery) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1159 }
1160
1161 void setWatchOutsideTouch(bool watchOutside) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1163 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001164
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001165 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1166
1167 void setInterceptsStylus(bool interceptsStylus) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1169 }
1170
1171 void setDropInput(bool dropInput) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1173 }
1174
1175 void setDropInputIfObscured(bool dropInputIfObscured) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1177 }
1178
1179 void setNoInputChannel(bool noInputChannel) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1181 }
1182
Josep del Riob3981622023-04-18 15:49:45 +00001183 void setDisableUserActivity(bool disableUserActivity) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1185 }
1186
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001187 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1188
chaviw3277faf2021-05-19 16:45:23 -05001189 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001190
Bernardo Rufino7393d172021-02-26 13:56:11 +00001191 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1192
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001193 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001194 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001195 mInfo.touchableRegion.clear();
1196 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001197
1198 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1199 ui::Transform translate;
1200 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1201 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001202 }
1203
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001204 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1205
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001206 void setIsWallpaper(bool isWallpaper) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1208 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001209
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001210 void setDupTouchToWallpaper(bool hasWallpaper) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1212 }
chaviwd1c23182019-12-20 18:44:56 -08001213
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001214 void setTrustedOverlay(bool trustedOverlay) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1216 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001217
chaviw9eaa22c2020-07-01 16:21:27 -07001218 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1219 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1220 }
1221
1222 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001223
yunho.shinf4a80b82020-11-16 21:13:57 +09001224 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1225
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001226 KeyEvent* consumeKey(bool handled = true) {
1227 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001228 if (event == nullptr) {
1229 ADD_FAILURE() << "Consume failed : no event";
1230 return nullptr;
1231 }
1232 if (event->getType() != InputEventType::KEY) {
1233 ADD_FAILURE() << "Instead of key event, got " << *event;
1234 return nullptr;
1235 }
1236 return static_cast<KeyEvent*>(event);
1237 }
1238
1239 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1240 KeyEvent* keyEvent = consumeKey();
1241 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1242 ASSERT_THAT(*keyEvent, matcher);
1243 }
1244
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001246 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001247 }
1248
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001250 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001251 }
1252
Svet Ganov5d3bc372020-01-26 23:11:07 -08001253 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001254 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001255 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1256 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001257 }
1258
1259 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001260 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001261 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1262 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001263 }
1264
1265 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001266 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001267 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1268 }
1269
1270 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1271 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001272 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001273 expectedFlags);
1274 }
1275
Svet Ganov5d3bc372020-01-26 23:11:07 -08001276 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001277 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1278 int32_t expectedFlags = 0) {
1279 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1280 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001281 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 }
1283
1284 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 int32_t expectedFlags = 0) {
1286 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1287 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001288 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001294 expectedFlags);
1295 }
1296
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001297 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1298 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001299 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001300 expectedFlags);
1301 }
1302
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001303 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1304 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001305 MotionEvent* motionEvent = consumeMotion();
1306 ASSERT_NE(nullptr, motionEvent);
1307 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1308 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1309 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001310 }
1311
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001312 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1313 ASSERT_NE(mInputReceiver, nullptr)
1314 << "Cannot consume events from a window with no receiver";
1315 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1316 }
1317
Prabir Pradhan99987712020-11-10 18:43:05 -08001318 void consumeCaptureEvent(bool hasCapture) {
1319 ASSERT_NE(mInputReceiver, nullptr)
1320 << "Cannot consume events from a window with no receiver";
1321 mInputReceiver->consumeCaptureEvent(hasCapture);
1322 }
1323
Prabir Pradhan5893d362023-11-17 04:30:40 +00001324 const MotionEvent& consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 MotionEvent* motionEvent = consumeMotion();
Prabir Pradhan5893d362023-11-17 04:30:40 +00001326 if (nullptr == motionEvent) {
1327 LOG(FATAL) << "Did not get a motion event, but expected " << matcher;
1328 }
1329 EXPECT_THAT(*motionEvent, matcher);
1330 return *motionEvent;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001331 }
1332
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001333 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001334 std::optional<int32_t> expectedDisplayId,
1335 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001336 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1337 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1338 expectedFlags);
1339 }
1340
arthurhungb89ccb02020-12-30 16:19:01 +08001341 void consumeDragEvent(bool isExiting, float x, float y) {
1342 mInputReceiver->consumeDragEvent(isExiting, x, y);
1343 }
1344
Antonio Kantekf16f2832021-09-28 04:39:20 +00001345 void consumeTouchModeEvent(bool inTouchMode) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1349 }
1350
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001351 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001352 if (mInputReceiver == nullptr) {
1353 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1354 return std::nullopt;
1355 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001356 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001357 }
1358
1359 void finishEvent(uint32_t sequenceNum) {
1360 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1361 mInputReceiver->finishEvent(sequenceNum);
1362 }
1363
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001364 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1365 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1366 mInputReceiver->sendTimeline(inputEventId, timeline);
1367 }
1368
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001369 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001370 if (mInputReceiver == nullptr) {
1371 return nullptr;
1372 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001373 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001374 }
1375
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001376 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001377 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001378 if (event == nullptr) {
1379 ADD_FAILURE() << "Consume failed : no event";
1380 return nullptr;
1381 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001382 if (event->getType() != InputEventType::MOTION) {
1383 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001384 return nullptr;
1385 }
1386 return static_cast<MotionEvent*>(event);
1387 }
1388
Arthur Hungb92218b2018-08-14 12:00:21 +08001389 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001390 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001391 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001392 return; // Can't receive events if the window does not have input channel
1393 }
1394 ASSERT_NE(nullptr, mInputReceiver)
1395 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001396 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001397 }
1398
chaviwaf87b3e2019-10-01 16:59:28 -07001399 sp<IBinder> getToken() { return mInfo.token; }
1400
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001401 const std::string& getName() { return mName; }
1402
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001403 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001404 mInfo.ownerPid = ownerPid;
1405 mInfo.ownerUid = ownerUid;
1406 }
1407
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001408 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001409
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001410 void destroyReceiver() { mInputReceiver = nullptr; }
1411
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001412 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1413
chaviwd1c23182019-12-20 18:44:56 -08001414private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001415 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001416 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001417 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001418 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001419 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001420};
1421
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001422std::atomic<int32_t> FakeWindowHandle::sId{1};
1423
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001424class FakeMonitorReceiver {
1425public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1427 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001430
1431 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1433 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001434 }
1435
1436 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001437 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001438 }
1439
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001440 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001441
1442 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001443 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1444 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001445 }
1446
1447 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001448 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1449 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001450 }
1451
1452 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001453 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1454 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001455 }
1456
1457 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001458 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001459 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1460 WithDisplayId(expectedDisplayId),
1461 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1462 }
1463
1464 void consumeMotionPointerDown(int32_t pointerIdx) {
1465 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1466 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001467 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1468 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001469 }
1470
1471 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001472 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001473 }
1474
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001475 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001477 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001478
1479private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001480 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001481};
1482
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001483static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001484 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001485 int32_t displayId = ADISPLAY_ID_NONE,
1486 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001487 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001488 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001489 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001490 KeyEvent event;
1491 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1492
1493 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001494 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001495 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1496 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001497
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498 if (!allowKeyRepeat) {
1499 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1500 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001501 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001502 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001503}
1504
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001505static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1506 InputEventInjectionResult result =
1507 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1508 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1509 if (result != InputEventInjectionResult::TIMED_OUT) {
1510 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1511 }
1512}
1513
1514static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001515 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001516 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001517}
1518
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001519// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1520// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1521// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001522static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1523 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001524 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001525 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001526 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001527}
1528
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001529static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001530 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001531 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001532}
1533
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001534static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001535 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001536 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001537 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001538 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1540 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001541}
1542
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001543static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001544 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1545 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001546 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001547 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1548 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001549 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001550 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001551 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001552 MotionEventBuilder motionBuilder =
1553 MotionEventBuilder(action, source)
1554 .displayId(displayId)
1555 .eventTime(eventTime)
1556 .rawXCursorPosition(cursorPosition.x)
1557 .rawYCursorPosition(cursorPosition.y)
1558 .pointer(
1559 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1560 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1561 motionBuilder.downTime(eventTime);
1562 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001563
1564 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001565 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1566 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001567}
1568
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001569static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1570 int32_t displayId,
1571 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001572 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001573}
1574
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001575static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1576 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001577 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001578 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001579}
1580
Jackal Guof9696682018-10-05 12:23:23 +08001581static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001584 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1585 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1586 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001587
1588 return args;
1589}
1590
Josep del Riob3981622023-04-18 15:49:45 +00001591static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1592 int32_t displayId = ADISPLAY_ID_NONE) {
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001595 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1596 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1597 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001598
1599 return args;
1600}
1601
1602static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1603 int32_t displayId = ADISPLAY_ID_NONE) {
1604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1605 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001606 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1607 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1608 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001609
1610 return args;
1611}
1612
Prabir Pradhan678438e2023-04-13 19:32:51 +00001613[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1614 int32_t displayId,
1615 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001616 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001617 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1618 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1619 }
1620
chaviwd1c23182019-12-20 18:44:56 -08001621 PointerProperties pointerProperties[pointerCount];
1622 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001623
chaviwd1c23182019-12-20 18:44:56 -08001624 for (size_t i = 0; i < pointerCount; i++) {
1625 pointerProperties[i].clear();
1626 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001627 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001628
chaviwd1c23182019-12-20 18:44:56 -08001629 pointerCoords[i].clear();
1630 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1631 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1632 }
Jackal Guof9696682018-10-05 12:23:23 +08001633
1634 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1635 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001636 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1637 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1638 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001639 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001640 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001641 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001642 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001643
1644 return args;
1645}
1646
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001647static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1648 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1649}
1650
chaviwd1c23182019-12-20 18:44:56 -08001651static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1652 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1653}
1654
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001655static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1656 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001657 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1658 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001659}
1660
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001661} // namespace
1662
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001663/**
1664 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1665 * broken channel.
1666 */
1667TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1669 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001670 sp<FakeWindowHandle>::make(application, mDispatcher,
1671 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001674
1675 // Window closes its channel, but the window remains.
1676 window->destroyReceiver();
1677 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1678}
1679
Arthur Hungb92218b2018-08-14 12:00:21 +08001680TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001682 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1683 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001684
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001689
1690 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001692}
1693
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001694TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1695 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001696 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1697 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001698
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001699 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001700 // Inject a MotionEvent to an unknown display.
1701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1704
1705 // Window should receive motion event.
1706 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1707}
1708
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001710 * Calling onWindowInfosChanged once should not cause any issues.
1711 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 * called twice.
1713 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001714TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001716 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1717 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001718 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001722 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001725
1726 // Window should receive motion event.
1727 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1728}
1729
1730/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001731 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732 */
1733TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001735 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1736 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001737 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001738
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001739 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1740 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001742 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001743 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001745
1746 // Window should receive motion event.
1747 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1748}
1749
Arthur Hungb92218b2018-08-14 12:00:21 +08001750// The foreground window should receive the first touch down event.
1751TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001753 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001754 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001755 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001756 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001757
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001758 mDispatcher->onWindowInfosChanged(
1759 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001761 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001763
1764 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001765 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001766 windowSecond->assertNoEvents();
1767}
1768
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769/**
1770 * Two windows: A top window, and a wallpaper behind the window.
1771 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1772 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001773 * 1. foregroundWindow <-- dup touch to wallpaper
1774 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 */
1776TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1778 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001779 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001780 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001782 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001783 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001785 mDispatcher->onWindowInfosChanged(
1786 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001788 injectMotionEvent(*mDispatcher,
1789 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1791 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1793
1794 // Both foreground window and its wallpaper should receive the touch down
1795 foregroundWindow->consumeMotionDown();
1796 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1797
1798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001799 injectMotionEvent(*mDispatcher,
1800 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1801 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1802 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1804
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001805 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001806 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1807
1808 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001809 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001810 foregroundWindow->consumeMotionCancel();
1811 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1812 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1813}
1814
1815/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001816 * Two fingers down on the window, and lift off the first finger.
1817 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1818 * contains a single pointer.
1819 */
1820TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1822 sp<FakeWindowHandle> window =
1823 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1824
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001825 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001826 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1828 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1829 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001830 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001831 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1832 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1833 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1834 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001835 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001836 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1837 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1838 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1839 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001840 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1841 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1842 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1843
1844 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001845 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001846 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1847 window->consumeMotionEvent(
1848 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1849}
1850
1851/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001852 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1853 * with the following differences:
1854 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1855 * clean up the connection.
1856 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1857 * Ensure that there's no crash in the dispatcher.
1858 */
1859TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1861 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001863 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001864 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001865 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001866 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001867
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001868 mDispatcher->onWindowInfosChanged(
1869 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001871 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001872 {100, 200}))
1873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1874
1875 // Both foreground window and its wallpaper should receive the touch down
1876 foregroundWindow->consumeMotionDown();
1877 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1878
1879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001880 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001881 ADISPLAY_ID_DEFAULT, {110, 200}))
1882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1883
1884 foregroundWindow->consumeMotionMove();
1885 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1886
1887 // Wallpaper closes its channel, but the window remains.
1888 wallpaperWindow->destroyReceiver();
1889 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1890
1891 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1892 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001893 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001894 foregroundWindow->consumeMotionCancel();
1895}
1896
Arthur Hungc539dbb2022-12-08 07:45:36 +00001897class ShouldSplitTouchFixture : public InputDispatcherTest,
1898 public ::testing::WithParamInterface<bool> {};
1899INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1900 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001901/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 * A single window that receives touch (on top), and a wallpaper window underneath it.
1903 * The top window gets a multitouch gesture.
1904 * Ensure that wallpaper gets the same gesture.
1905 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001906TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001908 sp<FakeWindowHandle> foregroundWindow =
1909 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1910 foregroundWindow->setDupTouchToWallpaper(true);
1911 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912
1913 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001914 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001915 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001917 mDispatcher->onWindowInfosChanged(
1918 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001919
1920 // Touch down on top window
1921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001922 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001923 {100, 100}))
1924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1925
1926 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001927 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1929
1930 // Second finger down on the top window
1931 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001932 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001934 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1935 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 .build();
1937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001938 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001939 InputEventInjectionSync::WAIT_FOR_RESULT))
1940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1941
Harry Cutts33476232023-01-30 19:57:29 +00001942 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1943 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001945
1946 const MotionEvent secondFingerUpEvent =
1947 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1948 .displayId(ADISPLAY_ID_DEFAULT)
1949 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001950 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1951 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952 .build();
1953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001954 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001955 InputEventInjectionSync::WAIT_FOR_RESULT))
1956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1957 foregroundWindow->consumeMotionPointerUp(0);
1958 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1959
1960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001961 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001962 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1963 AINPUT_SOURCE_TOUCHSCREEN)
1964 .displayId(ADISPLAY_ID_DEFAULT)
1965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001966 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001967 .x(100)
1968 .y(100))
1969 .build(),
1970 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001971 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1972 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1973 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974}
1975
1976/**
1977 * Two windows: a window on the left and window on the right.
1978 * A third window, wallpaper, is behind both windows, and spans both top windows.
1979 * The first touch down goes to the left window. A second pointer touches down on the right window.
1980 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1981 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1982 * ACTION_POINTER_DOWN(1).
1983 */
1984TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1985 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1986 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001987 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001989 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990
1991 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001992 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001994 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995
1996 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001997 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001999 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002001 mDispatcher->onWindowInfosChanged(
2002 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2003 {},
2004 0,
2005 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006
2007 // Touch down on left window
2008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002009 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002010 {100, 100}))
2011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2012
2013 // Both foreground window and its wallpaper should receive the touch down
2014 leftWindow->consumeMotionDown();
2015 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2016
2017 // Second finger down on the right window
2018 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002019 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002021 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2022 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 .build();
2024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002025 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 InputEventInjectionSync::WAIT_FOR_RESULT))
2027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2028
2029 leftWindow->consumeMotionMove();
2030 // Since the touch is split, right window gets ACTION_DOWN
2031 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002032 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 expectedWallpaperFlags);
2034
2035 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002036 mDispatcher->onWindowInfosChanged(
2037 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 leftWindow->consumeMotionCancel();
2039 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2040 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2041
2042 // The pointer that's still down on the right window moves, and goes to the right window only.
2043 // As far as the dispatcher's concerned though, both pointers are still present.
2044 const MotionEvent secondFingerMoveEvent =
2045 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2046 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002047 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2048 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 .build();
2050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002051 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002052 InputEventInjectionSync::WAIT_FOR_RESULT));
2053 rightWindow->consumeMotionMove();
2054
2055 leftWindow->assertNoEvents();
2056 rightWindow->assertNoEvents();
2057 wallpaperWindow->assertNoEvents();
2058}
2059
Arthur Hungc539dbb2022-12-08 07:45:36 +00002060/**
2061 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2062 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2063 * The right window should receive ACTION_DOWN.
2064 */
2065TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002067 sp<FakeWindowHandle> leftWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2069 leftWindow->setFrame(Rect(0, 0, 200, 200));
2070 leftWindow->setDupTouchToWallpaper(true);
2071 leftWindow->setSlippery(true);
2072
2073 sp<FakeWindowHandle> rightWindow =
2074 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2075 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002076
2077 sp<FakeWindowHandle> wallpaperWindow =
2078 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2079 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002080
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002081 mDispatcher->onWindowInfosChanged(
2082 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2083 {},
2084 0,
2085 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002086
Arthur Hungc539dbb2022-12-08 07:45:36 +00002087 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002089 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002090 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002092
2093 // Both foreground window and its wallpaper should receive the touch down
2094 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2096
Arthur Hungc539dbb2022-12-08 07:45:36 +00002097 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002099 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002100 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2102
Arthur Hungc539dbb2022-12-08 07:45:36 +00002103 leftWindow->consumeMotionCancel();
2104 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2105 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002106}
2107
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002108/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002109 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2110 * interactive, it might stop sending this flag.
2111 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2112 * to have a consistent input stream.
2113 *
2114 * Test procedure:
2115 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2116 * DOWN (new gesture).
2117 *
2118 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2119 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2120 *
2121 * We technically just need a single window here, but we are using two windows (spy on top and a
2122 * regular window below) to emulate the actual situation where it happens on the device.
2123 */
2124TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2126 sp<FakeWindowHandle> spyWindow =
2127 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2128 spyWindow->setFrame(Rect(0, 0, 200, 200));
2129 spyWindow->setTrustedOverlay(true);
2130 spyWindow->setSpy(true);
2131
2132 sp<FakeWindowHandle> window =
2133 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2134 window->setFrame(Rect(0, 0, 200, 200));
2135
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002136 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002137 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002138
2139 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002140 mDispatcher->notifyMotion(
2141 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2142 .deviceId(touchDeviceId)
2143 .policyFlags(DEFAULT_POLICY_FLAGS)
2144 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2145 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002146
Prabir Pradhan678438e2023-04-13 19:32:51 +00002147 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2148 .deviceId(touchDeviceId)
2149 .policyFlags(DEFAULT_POLICY_FLAGS)
2150 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2151 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2152 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002153 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2154 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2155 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2156 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2157
2158 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002159 mDispatcher->notifyMotion(
2160 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2161 .deviceId(touchDeviceId)
2162 .policyFlags(0)
2163 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2164 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2165 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002166 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2167 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2168
2169 // We don't need to reset the device to reproduce the issue, but the reset event typically
2170 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002171 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002172
2173 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002174 mDispatcher->notifyMotion(
2175 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2176 .deviceId(touchDeviceId)
2177 .policyFlags(DEFAULT_POLICY_FLAGS)
2178 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2179 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002180 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2181 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2182
2183 // No more events
2184 spyWindow->assertNoEvents();
2185 window->assertNoEvents();
2186}
2187
2188/**
Linnan Li907ae732023-09-05 17:14:21 +08002189 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2190 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2191 * interactive, it might stop sending this flag.
2192 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2193 * the consistency of the hover event in this case.
2194 *
2195 * Test procedure:
2196 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2197 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2198 *
2199 * We expect to receive two full streams of hover events.
2200 */
2201TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2203
2204 sp<FakeWindowHandle> window =
2205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2206 window->setFrame(Rect(0, 0, 300, 300));
2207
2208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2209
2210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2211 .policyFlags(DEFAULT_POLICY_FLAGS)
2212 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2213 .build());
2214 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2215
2216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2217 .policyFlags(DEFAULT_POLICY_FLAGS)
2218 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2219 .build());
2220 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2221
2222 // Send hover exit without the default policy flags.
2223 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2224 .policyFlags(0)
2225 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2226 .build());
2227
2228 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2229
2230 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2231 // right event.
2232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2233 .policyFlags(DEFAULT_POLICY_FLAGS)
2234 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2235 .build());
2236 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2237
2238 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2239 .policyFlags(DEFAULT_POLICY_FLAGS)
2240 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2241 .build());
2242 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2243
2244 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2245 .policyFlags(DEFAULT_POLICY_FLAGS)
2246 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2247 .build());
2248 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2249}
2250
2251/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002252 * Two windows: a window on the left and a window on the right.
2253 * Mouse is hovered from the right window into the left window.
2254 * Next, we tap on the left window, where the cursor was last seen.
2255 * The second tap is done onto the right window.
2256 * The mouse and tap are from two different devices.
2257 * We technically don't need to set the downtime / eventtime for these events, but setting these
2258 * explicitly helps during debugging.
2259 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2260 * In the buggy implementation, a tap on the right window would cause a crash.
2261 */
2262TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2263 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2264 sp<FakeWindowHandle> leftWindow =
2265 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2266 leftWindow->setFrame(Rect(0, 0, 200, 200));
2267
2268 sp<FakeWindowHandle> rightWindow =
2269 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2270 rightWindow->setFrame(Rect(200, 0, 400, 200));
2271
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002272 mDispatcher->onWindowInfosChanged(
2273 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002274 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2275 // stale.
2276 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2277 const int32_t mouseDeviceId = 6;
2278 const int32_t touchDeviceId = 4;
2279 // Move the cursor from right
2280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002281 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002282 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2283 AINPUT_SOURCE_MOUSE)
2284 .deviceId(mouseDeviceId)
2285 .downTime(baseTime + 10)
2286 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002287 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002288 .build()));
2289 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2290
2291 // .. to the left window
2292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002293 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002294 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2295 AINPUT_SOURCE_MOUSE)
2296 .deviceId(mouseDeviceId)
2297 .downTime(baseTime + 10)
2298 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002299 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002300 .build()));
2301 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2303 // Now tap the left window
2304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002305 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002306 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2307 AINPUT_SOURCE_TOUCHSCREEN)
2308 .deviceId(touchDeviceId)
2309 .downTime(baseTime + 40)
2310 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002311 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002312 .build()));
2313 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2314 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2315
2316 // release tap
2317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002319 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2320 AINPUT_SOURCE_TOUCHSCREEN)
2321 .deviceId(touchDeviceId)
2322 .downTime(baseTime + 40)
2323 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002324 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002325 .build()));
2326 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2327
2328 // Tap the window on the right
2329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002330 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002331 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2332 AINPUT_SOURCE_TOUCHSCREEN)
2333 .deviceId(touchDeviceId)
2334 .downTime(baseTime + 60)
2335 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002336 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002337 .build()));
2338 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2339
2340 // release tap
2341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002342 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002343 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2344 AINPUT_SOURCE_TOUCHSCREEN)
2345 .deviceId(touchDeviceId)
2346 .downTime(baseTime + 60)
2347 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002348 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002349 .build()));
2350 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2351
2352 // No more events
2353 leftWindow->assertNoEvents();
2354 rightWindow->assertNoEvents();
2355}
2356
2357/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002358 * Start hovering in a window. While this hover is still active, make another window appear on top.
2359 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2360 * While the top window is present, the hovering is stopped.
2361 * Later, hovering gets resumed again.
2362 * Ensure that new hover gesture is handled correctly.
2363 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2364 * to the window that's currently being hovered over.
2365 */
2366TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2368 sp<FakeWindowHandle> window =
2369 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2370 window->setFrame(Rect(0, 0, 200, 200));
2371
2372 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002373 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002374
2375 // Start hovering in the window
2376 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2377 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2378 .build());
2379 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2380
2381 // Now, an obscuring window appears!
2382 sp<FakeWindowHandle> obscuringWindow =
2383 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2384 ADISPLAY_ID_DEFAULT,
2385 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2386 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2387 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2388 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2389 obscuringWindow->setNoInputChannel(true);
2390 obscuringWindow->setFocusable(false);
2391 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002392 mDispatcher->onWindowInfosChanged(
2393 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002394
2395 // While this new obscuring window is present, the hovering is stopped
2396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2397 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2398 .build());
2399 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2400
2401 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002403
2404 // And a new hover gesture starts.
2405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2406 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2407 .build());
2408 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2409}
2410
2411/**
2412 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2413 * the obscuring window.
2414 */
2415TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2417 sp<FakeWindowHandle> window =
2418 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2419 window->setFrame(Rect(0, 0, 200, 200));
2420
2421 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002422 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002423
2424 // Start hovering in the window
2425 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2426 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2427 .build());
2428 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2429
2430 // Now, an obscuring window appears!
2431 sp<FakeWindowHandle> obscuringWindow =
2432 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2433 ADISPLAY_ID_DEFAULT,
2434 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2435 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2436 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2437 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2438 obscuringWindow->setNoInputChannel(true);
2439 obscuringWindow->setFocusable(false);
2440 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002441 mDispatcher->onWindowInfosChanged(
2442 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002443
2444 // While this new obscuring window is present, the hovering continues. The event can't go to the
2445 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2448 .build());
2449 obscuringWindow->assertNoEvents();
2450 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2451
2452 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002454
2455 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2456 // so it should generate a HOVER_ENTER
2457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2458 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2459 .build());
2460 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2461
2462 // Now the MOVE should be getting dispatched normally
2463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2464 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2465 .build());
2466 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2467}
2468
2469/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002470 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2471 * events are delivered to the window.
2472 */
2473TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2475 sp<FakeWindowHandle> window =
2476 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2477 window->setFrame(Rect(0, 0, 200, 200));
2478 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2479
2480 // Start hovering in the window
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2485
2486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2487 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2488 .build());
2489 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2490
2491 // Scroll with the mouse
2492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2493 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2494 .build());
2495 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2496}
2497
2498using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2499
2500/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002501 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2502 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002503 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002504TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002505 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2506 sp<FakeWindowHandle> window =
2507 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2508 window->setFrame(Rect(0, 0, 200, 200));
2509
2510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2511
2512 constexpr int32_t touchDeviceId = 4;
2513 constexpr int32_t stylusDeviceId = 2;
2514
2515 // Stylus down
2516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2517 .deviceId(stylusDeviceId)
2518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2519 .build());
2520 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2521
2522 // Touch down
2523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2524 .deviceId(touchDeviceId)
2525 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2526 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002527
2528 // Touch move
2529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2530 .deviceId(touchDeviceId)
2531 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2532 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002533 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002534
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002535 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2537 .deviceId(stylusDeviceId)
2538 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2539 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002540 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2541 WithCoords(101, 111)));
2542
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002543 window->assertNoEvents();
2544}
2545
2546/**
2547 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002548 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002549 * Similar test as above, but with added SPY window.
2550 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002551TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2553 sp<FakeWindowHandle> window =
2554 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2555 sp<FakeWindowHandle> spyWindow =
2556 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2557 spyWindow->setFrame(Rect(0, 0, 200, 200));
2558 spyWindow->setTrustedOverlay(true);
2559 spyWindow->setSpy(true);
2560 window->setFrame(Rect(0, 0, 200, 200));
2561
2562 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2563
2564 constexpr int32_t touchDeviceId = 4;
2565 constexpr int32_t stylusDeviceId = 2;
2566
2567 // Stylus down
2568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2569 .deviceId(stylusDeviceId)
2570 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2571 .build());
2572 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2573 spyWindow->consumeMotionEvent(
2574 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2575
2576 // Touch down
2577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2578 .deviceId(touchDeviceId)
2579 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2580 .build());
2581
2582 // Touch move
2583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2584 .deviceId(touchDeviceId)
2585 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2586 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002587
2588 // Touch is ignored because stylus is already down
2589
2590 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2592 .deviceId(stylusDeviceId)
2593 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2594 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002595 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2596 WithCoords(101, 111)));
2597 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2598 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002599
2600 window->assertNoEvents();
2601 spyWindow->assertNoEvents();
2602}
2603
2604/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002605 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002606 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002607 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002608TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2610 sp<FakeWindowHandle> window =
2611 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2612 window->setFrame(Rect(0, 0, 200, 200));
2613
2614 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2615
2616 constexpr int32_t touchDeviceId = 4;
2617 constexpr int32_t stylusDeviceId = 2;
2618
2619 // Stylus down on the window
2620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2621 .deviceId(stylusDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2623 .build());
2624 window->consumeMotionEvent(
2625 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2626
2627 // Touch down on window
2628 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2629 .deviceId(touchDeviceId)
2630 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2631 .build());
2632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2633 .deviceId(touchDeviceId)
2634 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2635 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002637 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002638
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002639 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2641 .deviceId(stylusDeviceId)
2642 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2643 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002644 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2645 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002646
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002647 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2649 .deviceId(touchDeviceId)
2650 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2651 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002652 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002653}
2654
2655/**
2656 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002657 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002658 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002659TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2661 sp<FakeWindowHandle> window =
2662 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2663 window->setFrame(Rect(0, 0, 200, 200));
2664
2665 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2666
2667 constexpr int32_t touchDeviceId = 4;
2668 constexpr int32_t stylusDeviceId = 2;
2669
2670 // Touch down on window
2671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2672 .deviceId(touchDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2674 .build());
2675 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2676 .deviceId(touchDeviceId)
2677 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2678 .build());
2679 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2680 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2681
2682 // Stylus hover on the window
2683 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2684 .deviceId(stylusDeviceId)
2685 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2686 .build());
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2688 .deviceId(stylusDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2690 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002691 // Stylus hover movement causes touch to be canceled
2692 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2693 WithCoords(141, 146)));
2694 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2695 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2696 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2697 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002698
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002699 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2701 .deviceId(touchDeviceId)
2702 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2703 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002704
2705 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002706}
2707
2708/**
2709 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2710 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2711 * become active.
2712 */
2713TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2715 sp<FakeWindowHandle> window =
2716 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2717 window->setFrame(Rect(0, 0, 200, 200));
2718
2719 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2720
2721 constexpr int32_t stylusDeviceId1 = 3;
2722 constexpr int32_t stylusDeviceId2 = 5;
2723
2724 // Touch down on window
2725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2726 .deviceId(stylusDeviceId1)
2727 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2728 .build());
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2730 .deviceId(stylusDeviceId1)
2731 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2732 .build());
2733 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2734 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2735
2736 // Second stylus down
2737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2738 .deviceId(stylusDeviceId2)
2739 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2740 .build());
2741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId2)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2744 .build());
2745
2746 // First stylus is canceled, second one takes over.
2747 window->consumeMotionEvent(
2748 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2749 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2750 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2751
2752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2753 .deviceId(stylusDeviceId1)
2754 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2755 .build());
2756 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002757 window->assertNoEvents();
2758}
2759
2760/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002761 * One window. Touch down on the window. Then, stylus down on the window from another device.
2762 * Ensure that is canceled, because stylus down should be preferred over touch.
2763 */
2764TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2766 sp<FakeWindowHandle> window =
2767 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2768 window->setFrame(Rect(0, 0, 200, 200));
2769
2770 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2771
2772 constexpr int32_t touchDeviceId = 4;
2773 constexpr int32_t stylusDeviceId = 2;
2774
2775 // Touch down on window
2776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2777 .deviceId(touchDeviceId)
2778 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2779 .build());
2780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2781 .deviceId(touchDeviceId)
2782 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2783 .build());
2784 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2785 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2786
2787 // Stylus down on the window
2788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2789 .deviceId(stylusDeviceId)
2790 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2791 .build());
2792 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2793 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2794
2795 // Subsequent stylus movements are delivered correctly
2796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2797 .deviceId(stylusDeviceId)
2798 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2799 .build());
2800 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2801 WithCoords(101, 111)));
2802}
2803
2804/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002805 * Two windows: a window on the left and a window on the right.
2806 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2807 * down. Then, on the left window, also place second touch pointer down.
2808 * This test tries to reproduce a crash.
2809 * In the buggy implementation, second pointer down on the left window would cause a crash.
2810 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002811TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2813 sp<FakeWindowHandle> leftWindow =
2814 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2815 leftWindow->setFrame(Rect(0, 0, 200, 200));
2816
2817 sp<FakeWindowHandle> rightWindow =
2818 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2819 rightWindow->setFrame(Rect(200, 0, 400, 200));
2820
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002821 mDispatcher->onWindowInfosChanged(
2822 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002823
2824 const int32_t touchDeviceId = 4;
2825 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002826
2827 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2829 .deviceId(mouseDeviceId)
2830 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2831 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002832 leftWindow->consumeMotionEvent(
2833 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2834
2835 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002836 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2837 .deviceId(mouseDeviceId)
2838 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2839 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2840 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002841
2842 leftWindow->consumeMotionEvent(
2843 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2844 leftWindow->consumeMotionEvent(
2845 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2846
Prabir Pradhan678438e2023-04-13 19:32:51 +00002847 mDispatcher->notifyMotion(
2848 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2849 .deviceId(mouseDeviceId)
2850 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2851 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2853 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002854 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2855
2856 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2858 .deviceId(touchDeviceId)
2859 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2860 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002861 leftWindow->assertNoEvents();
2862
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2864
2865 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002866 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2867 .deviceId(touchDeviceId)
2868 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2869 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2870 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002871 // Since this is now a new splittable pointer going down on the left window, and it's coming
2872 // from a different device, the current gesture in the left window (pointer down) should first
2873 // be canceled.
2874 leftWindow->consumeMotionEvent(
2875 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002876 leftWindow->consumeMotionEvent(
2877 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2878 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2879 // current implementation.
2880 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2881 rightWindow->consumeMotionEvent(
2882 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2883
2884 leftWindow->assertNoEvents();
2885 rightWindow->assertNoEvents();
2886}
2887
2888/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002889 * Two windows: a window on the left and a window on the right.
2890 * Mouse is hovered on the left window and stylus is hovered on the right window.
2891 */
2892TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2894 sp<FakeWindowHandle> leftWindow =
2895 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2896 leftWindow->setFrame(Rect(0, 0, 200, 200));
2897
2898 sp<FakeWindowHandle> rightWindow =
2899 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2900 rightWindow->setFrame(Rect(200, 0, 400, 200));
2901
2902 mDispatcher->onWindowInfosChanged(
2903 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2904
2905 const int32_t stylusDeviceId = 3;
2906 const int32_t mouseDeviceId = 6;
2907
2908 // Start hovering over the left window
2909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2910 .deviceId(mouseDeviceId)
2911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2912 .build());
2913 leftWindow->consumeMotionEvent(
2914 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2915
2916 // Stylus hovered on right window
2917 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2918 .deviceId(stylusDeviceId)
2919 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2920 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002921 rightWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2923
2924 // Subsequent HOVER_MOVE events are dispatched correctly.
2925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2926 .deviceId(mouseDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2928 .build());
2929 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002930 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931
2932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2933 .deviceId(stylusDeviceId)
2934 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2935 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002936 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002937 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002938
2939 leftWindow->assertNoEvents();
2940 rightWindow->assertNoEvents();
2941}
2942
2943/**
2944 * Three windows: a window on the left and a window on the right.
2945 * And a spy window that's positioned above all of them.
2946 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2947 * Check the stream that's received by the spy.
2948 */
2949TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2951
2952 sp<FakeWindowHandle> spyWindow =
2953 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2954 spyWindow->setFrame(Rect(0, 0, 400, 400));
2955 spyWindow->setTrustedOverlay(true);
2956 spyWindow->setSpy(true);
2957
2958 sp<FakeWindowHandle> leftWindow =
2959 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2960 leftWindow->setFrame(Rect(0, 0, 200, 200));
2961
2962 sp<FakeWindowHandle> rightWindow =
2963 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2964
2965 rightWindow->setFrame(Rect(200, 0, 400, 200));
2966
2967 mDispatcher->onWindowInfosChanged(
2968 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2969
2970 const int32_t stylusDeviceId = 1;
2971 const int32_t touchDeviceId = 2;
2972
2973 // Stylus down on the left window
2974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2975 .deviceId(stylusDeviceId)
2976 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2977 .build());
2978 leftWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2980 spyWindow->consumeMotionEvent(
2981 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2982
2983 // Touch down on the right window
2984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2985 .deviceId(touchDeviceId)
2986 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2987 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002988 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989 rightWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002992 // Spy window does not receive touch events, because stylus events take precedence, and it
2993 // already has an active stylus gesture.
2994
2995 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2997 .deviceId(stylusDeviceId)
2998 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2999 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003000 leftWindow->consumeMotionEvent(
3001 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3002 spyWindow->consumeMotionEvent(
3003 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003004
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003005 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3007 .deviceId(touchDeviceId)
3008 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3009 .build());
3010 rightWindow->consumeMotionEvent(
3011 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003012
3013 spyWindow->assertNoEvents();
3014 leftWindow->assertNoEvents();
3015 rightWindow->assertNoEvents();
3016}
3017
3018/**
3019 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3020 * both.
3021 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003022 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003023 * At the same time, left and right should be getting independent streams of hovering and touch,
3024 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003025 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003026TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3028
3029 sp<FakeWindowHandle> spyWindow =
3030 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3031 spyWindow->setFrame(Rect(0, 0, 400, 400));
3032 spyWindow->setTrustedOverlay(true);
3033 spyWindow->setSpy(true);
3034
3035 sp<FakeWindowHandle> leftWindow =
3036 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3037 leftWindow->setFrame(Rect(0, 0, 200, 200));
3038
3039 sp<FakeWindowHandle> rightWindow =
3040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3041 rightWindow->setFrame(Rect(200, 0, 400, 200));
3042
3043 mDispatcher->onWindowInfosChanged(
3044 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3045
3046 const int32_t stylusDeviceId = 1;
3047 const int32_t touchDeviceId = 2;
3048
3049 // Stylus hover on the left window
3050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3051 .deviceId(stylusDeviceId)
3052 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3053 .build());
3054 leftWindow->consumeMotionEvent(
3055 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3056 spyWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3058
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003059 // Touch down on the right window. Spy doesn't receive this touch because it already has
3060 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3062 .deviceId(touchDeviceId)
3063 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3064 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003065 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003066 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003067 rightWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3069
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003070 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3072 .deviceId(stylusDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3074 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003075 leftWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 spyWindow->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003080 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3082 .deviceId(touchDeviceId)
3083 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3084 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003085 rightWindow->consumeMotionEvent(
3086 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3087
3088 spyWindow->assertNoEvents();
3089 leftWindow->assertNoEvents();
3090 rightWindow->assertNoEvents();
3091}
3092
3093/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003094 * On a single window, use two different devices: mouse and touch.
3095 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3096 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3097 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3098 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3099 * represent a new gesture.
3100 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003101TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3103 sp<FakeWindowHandle> window =
3104 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3105 window->setFrame(Rect(0, 0, 400, 400));
3106
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003107 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108
3109 const int32_t touchDeviceId = 4;
3110 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003111
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003112 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3116 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003118 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3119 .deviceId(touchDeviceId)
3120 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3121 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3122 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003123 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003124 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3125 .deviceId(touchDeviceId)
3126 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3127 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3128 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003129 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3130 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3131 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3132
3133 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003134 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3135 .deviceId(mouseDeviceId)
3136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3138 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139
3140 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003141 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003142 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3143
Prabir Pradhan678438e2023-04-13 19:32:51 +00003144 mDispatcher->notifyMotion(
3145 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3146 .deviceId(mouseDeviceId)
3147 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3148 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3150 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003151 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3152
3153 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003154 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3155 .deviceId(touchDeviceId)
3156 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3157 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3158 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003159 // Since we already canceled this touch gesture, it will be ignored until a completely new
3160 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3161 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3162 // However, mouse movements should continue to work.
3163 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3164 .deviceId(mouseDeviceId)
3165 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3167 .build());
3168 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3169
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003170 window->assertNoEvents();
3171}
3172
3173/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003174 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3175 * the injected event.
3176 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003177TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3179 sp<FakeWindowHandle> window =
3180 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3181 window->setFrame(Rect(0, 0, 400, 400));
3182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003184
3185 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003186 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3187 // completion.
3188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003189 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003190 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3191 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003192 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003193 .build()));
3194 window->consumeMotionEvent(
3195 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3196
3197 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3198 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3200 .deviceId(touchDeviceId)
3201 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3202 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003203
3204 window->consumeMotionEvent(
3205 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3206 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3207}
3208
3209/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003210 * This test is similar to the test above, but the sequence of injected events is different.
3211 *
3212 * Two windows: a window on the left and a window on the right.
3213 * Mouse is hovered over the left window.
3214 * Next, we tap on the left window, where the cursor was last seen.
3215 *
3216 * After that, we inject one finger down onto the right window, and then a second finger down onto
3217 * the left window.
3218 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3219 * window (first), and then another on the left window (second).
3220 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3221 * In the buggy implementation, second finger down on the left window would cause a crash.
3222 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003223TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3225 sp<FakeWindowHandle> leftWindow =
3226 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3227 leftWindow->setFrame(Rect(0, 0, 200, 200));
3228
3229 sp<FakeWindowHandle> rightWindow =
3230 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3231 rightWindow->setFrame(Rect(200, 0, 400, 200));
3232
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003233 mDispatcher->onWindowInfosChanged(
3234 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003235
3236 const int32_t mouseDeviceId = 6;
3237 const int32_t touchDeviceId = 4;
3238 // Hover over the left window. Keep the cursor there.
3239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003240 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003241 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3242 AINPUT_SOURCE_MOUSE)
3243 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003244 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003245 .build()));
3246 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3247
3248 // Tap on left window
3249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003250 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003251 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3252 AINPUT_SOURCE_TOUCHSCREEN)
3253 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003254 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003255 .build()));
3256
3257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003258 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003259 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3260 AINPUT_SOURCE_TOUCHSCREEN)
3261 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003262 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003263 .build()));
3264 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3265 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3266 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3267
3268 // First finger down on right window
3269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003271 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3272 AINPUT_SOURCE_TOUCHSCREEN)
3273 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003274 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003275 .build()));
3276 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3277
3278 // Second finger down on the left window
3279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003280 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003281 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3282 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003283 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3284 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003285 .build()));
3286 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3287 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3288
3289 // No more events
3290 leftWindow->assertNoEvents();
3291 rightWindow->assertNoEvents();
3292}
3293
3294/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003295 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3296 * While the touch is down, new hover events from the stylus device should be ignored. After the
3297 * touch is gone, stylus hovering should start working again.
3298 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003299TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3301 sp<FakeWindowHandle> window =
3302 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3303 window->setFrame(Rect(0, 0, 200, 200));
3304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003306
3307 const int32_t stylusDeviceId = 5;
3308 const int32_t touchDeviceId = 4;
3309 // Start hovering with stylus
3310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003311 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003312 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003314 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003315 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003316 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003317
3318 // Finger down on the window
3319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003320 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003321 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003322 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003323 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003324 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003325 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003326
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003327 // Continue hovering with stylus.
3328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003329 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3331 AINPUT_SOURCE_STYLUS)
3332 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003333 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003334 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003335 // Hovers continue to work
3336 window->consumeMotionEvent(
3337 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003338
3339 // Lift up the finger
3340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003342 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3343 AINPUT_SOURCE_TOUCHSCREEN)
3344 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003347
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003350 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3351 AINPUT_SOURCE_STYLUS)
3352 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003353 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003354 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003355 window->consumeMotionEvent(
3356 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003357 window->assertNoEvents();
3358}
3359
3360/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003361 * A spy window above a window with no input channel.
3362 * Start hovering with a stylus device, and then tap with it.
3363 * Ensure spy window receives the entire sequence.
3364 */
3365TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3367 sp<FakeWindowHandle> spyWindow =
3368 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3369 spyWindow->setFrame(Rect(0, 0, 200, 200));
3370 spyWindow->setTrustedOverlay(true);
3371 spyWindow->setSpy(true);
3372 sp<FakeWindowHandle> window =
3373 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3374 window->setNoInputChannel(true);
3375 window->setFrame(Rect(0, 0, 200, 200));
3376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003377 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003378
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003379 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3381 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3382 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003383 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3384 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3386 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3387 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003388 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3389
3390 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3392 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3393 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003394 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3395
3396 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3398 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3399 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003400 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3401
3402 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3405 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003406 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3407 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3409 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3410 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003411 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3412
3413 // No more events
3414 spyWindow->assertNoEvents();
3415 window->assertNoEvents();
3416}
3417
3418/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003419 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3420 * rejected. But since we already have an ongoing gesture, this event should be processed.
3421 * This prevents inconsistent events being handled inside the dispatcher.
3422 */
3423TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3425
3426 sp<FakeWindowHandle> window =
3427 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3428 window->setFrame(Rect(0, 0, 200, 200));
3429
3430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3431
3432 // Start hovering with stylus
3433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3434 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3435 .build());
3436 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3437
3438 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3439 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3440 .build();
3441 // Make this 'hoverExit' event stale
3442 mFakePolicy->setStaleEventTimeout(100ms);
3443 std::this_thread::sleep_for(100ms);
3444
3445 // It shouldn't be dropped by the dispatcher, even though it's stale.
3446 mDispatcher->notifyMotion(hoverExit);
3447 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3448
3449 // Stylus starts hovering again! There should be no crash.
3450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3451 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3452 .build());
3453 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3454}
3455
3456/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003457 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3458 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3459 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3460 * While the mouse is down, new move events from the touch device should be ignored.
3461 */
3462TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3464 sp<FakeWindowHandle> spyWindow =
3465 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3466 spyWindow->setFrame(Rect(0, 0, 200, 200));
3467 spyWindow->setTrustedOverlay(true);
3468 spyWindow->setSpy(true);
3469 sp<FakeWindowHandle> window =
3470 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3471 window->setFrame(Rect(0, 0, 200, 200));
3472
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003473 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003474
3475 const int32_t mouseDeviceId = 7;
3476 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003477
3478 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3480 .deviceId(mouseDeviceId)
3481 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3482 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003483 spyWindow->consumeMotionEvent(
3484 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3485 window->consumeMotionEvent(
3486 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3487
3488 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3490 .deviceId(touchDeviceId)
3491 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3492 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003493 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3494 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3495 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3496 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3497
Prabir Pradhan678438e2023-04-13 19:32:51 +00003498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3499 .deviceId(touchDeviceId)
3500 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3501 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003502 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3503 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3504
3505 // Pilfer the stream
3506 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3507 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3508
Prabir Pradhan678438e2023-04-13 19:32:51 +00003509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3510 .deviceId(touchDeviceId)
3511 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3512 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003513 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3514
3515 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3517 .deviceId(mouseDeviceId)
3518 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3519 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521
3522 spyWindow->consumeMotionEvent(
3523 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3524 spyWindow->consumeMotionEvent(
3525 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3526 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3527
Prabir Pradhan678438e2023-04-13 19:32:51 +00003528 mDispatcher->notifyMotion(
3529 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3530 .deviceId(mouseDeviceId)
3531 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3532 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3533 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3534 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003535 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3536 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3537
3538 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3540 .deviceId(mouseDeviceId)
3541 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3542 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3543 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003544 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3545 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3546
3547 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3549 .deviceId(touchDeviceId)
3550 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3551 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003552
3553 // No more events
3554 spyWindow->assertNoEvents();
3555 window->assertNoEvents();
3556}
3557
3558/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003559 * On the display, have a single window, and also an area where there's no window.
3560 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3561 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3562 */
3563TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3565 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003566 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003567
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003568 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003569
3570 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003571 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003572
3573 mDispatcher->waitForIdle();
3574 window->assertNoEvents();
3575
3576 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003577 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003578 mDispatcher->waitForIdle();
3579 window->consumeMotionDown();
3580}
3581
3582/**
3583 * Same test as above, but instead of touching the empty space, the first touch goes to
3584 * non-touchable window.
3585 */
3586TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3588 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003589 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003590 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3591 window1->setTouchable(false);
3592 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003593 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003594 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3595
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003596 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003597
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003598 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003599 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003600
3601 mDispatcher->waitForIdle();
3602 window1->assertNoEvents();
3603 window2->assertNoEvents();
3604
3605 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003606 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003607 mDispatcher->waitForIdle();
3608 window2->consumeMotionDown();
3609}
3610
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003611/**
3612 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3613 * to the event time of the first ACTION_DOWN sent to the particular window.
3614 */
3615TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3617 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003618 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003619 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3620 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003621 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3623
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003624 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003625
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003626 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003627 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003628
3629 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003630
3631 MotionEvent* motionEvent1 = window1->consumeMotion();
3632 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003633 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003634 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3635 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003636
3637 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003639 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003640 MotionEvent* motionEvent2 = window2->consumeMotion();
3641 ASSERT_NE(motionEvent2, nullptr);
3642 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003643 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003644 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003645
3646 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003647 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003648 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003649 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003650
3651 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003652 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003653 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003654 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003655
3656 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3657 window1->consumeMotionMove();
3658 window1->assertNoEvents();
3659
3660 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003661 mDispatcher->notifyMotion(
3662 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003663 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003664 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003665
Prabir Pradhan678438e2023-04-13 19:32:51 +00003666 mDispatcher->notifyMotion(
3667 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003668 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003669 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003670}
3671
Garfield Tandf26e862020-07-01 20:18:19 -07003672TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003674 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003675 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003676 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003677 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003678 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003679 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003680
3681 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3682
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003683 mDispatcher->onWindowInfosChanged(
3684 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003685
3686 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003688 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003689 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3690 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003691 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003692 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003693 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003694
3695 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003697 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003698 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3699 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003700 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003701 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003702 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3703 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003704
3705 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003707 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003708 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3709 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003710 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003711 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003712 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3713 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003714
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003716 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003717 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3718 AINPUT_SOURCE_MOUSE)
3719 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3720 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003721 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003722 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003723 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003724
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003726 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003727 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3728 AINPUT_SOURCE_MOUSE)
3729 .buttonState(0)
3730 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003731 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003732 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003733 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003734
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003736 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003737 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3738 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003739 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003740 .build()));
3741 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3742
3743 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003745 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003746 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3747 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003749 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003750 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003751
3752 // No more events
3753 windowLeft->assertNoEvents();
3754 windowRight->assertNoEvents();
3755}
3756
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003757/**
3758 * Put two fingers down (and don't release them) and click the mouse button.
3759 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3760 * currently active gesture should be canceled, and the new one should proceed.
3761 */
3762TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3763 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3764 sp<FakeWindowHandle> window =
3765 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3766 window->setFrame(Rect(0, 0, 600, 800));
3767
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003769
3770 const int32_t touchDeviceId = 4;
3771 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003772
3773 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3775 .deviceId(touchDeviceId)
3776 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3777 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003778
Prabir Pradhan678438e2023-04-13 19:32:51 +00003779 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3780 .deviceId(touchDeviceId)
3781 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3782 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3783 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003784 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3785 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3786
3787 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3789 .deviceId(mouseDeviceId)
3790 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3791 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3792 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003793 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3794 WithPointerCount(2u)));
3795 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3796
Prabir Pradhan678438e2023-04-13 19:32:51 +00003797 mDispatcher->notifyMotion(
3798 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3799 .deviceId(mouseDeviceId)
3800 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3801 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3802 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3803 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003804 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3805
3806 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3807 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3809 .deviceId(touchDeviceId)
3810 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3811 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3812 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003813 window->assertNoEvents();
3814}
3815
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003816TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3818
3819 sp<FakeWindowHandle> spyWindow =
3820 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3821 spyWindow->setFrame(Rect(0, 0, 600, 800));
3822 spyWindow->setTrustedOverlay(true);
3823 spyWindow->setSpy(true);
3824 sp<FakeWindowHandle> window =
3825 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3826 window->setFrame(Rect(0, 0, 600, 800));
3827
3828 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003829 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003830
3831 // Send mouse cursor to the window
3832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003833 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003834 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3835 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003837 .build()));
3838
3839 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3840 WithSource(AINPUT_SOURCE_MOUSE)));
3841 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3842 WithSource(AINPUT_SOURCE_MOUSE)));
3843
3844 window->assertNoEvents();
3845 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003846}
3847
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003848TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3850
3851 sp<FakeWindowHandle> spyWindow =
3852 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3853 spyWindow->setFrame(Rect(0, 0, 600, 800));
3854 spyWindow->setTrustedOverlay(true);
3855 spyWindow->setSpy(true);
3856 sp<FakeWindowHandle> window =
3857 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3858 window->setFrame(Rect(0, 0, 600, 800));
3859
3860 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003861 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003862
3863 // Send mouse cursor to the window
3864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003865 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003866 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3867 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003868 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003869 .build()));
3870
3871 // Move mouse cursor
3872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003873 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003874 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3875 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003876 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003877 .build()));
3878
3879 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3880 WithSource(AINPUT_SOURCE_MOUSE)));
3881 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3882 WithSource(AINPUT_SOURCE_MOUSE)));
3883 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3884 WithSource(AINPUT_SOURCE_MOUSE)));
3885 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3886 WithSource(AINPUT_SOURCE_MOUSE)));
3887 // Touch down on the window
3888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003889 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003890 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3891 AINPUT_SOURCE_TOUCHSCREEN)
3892 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003893 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003894 .build()));
3895 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3896 WithSource(AINPUT_SOURCE_MOUSE)));
3897 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3898 WithSource(AINPUT_SOURCE_MOUSE)));
3899 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3900 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3901 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3902 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3903
3904 // pilfer the motion, retaining the gesture on the spy window.
3905 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3906 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3907 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3908
3909 // Touch UP on the window
3910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003911 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003912 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3913 AINPUT_SOURCE_TOUCHSCREEN)
3914 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003915 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003916 .build()));
3917 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3918 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3919
3920 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3921 // to send a new gesture. It should again go to both windows (spy and the window below), just
3922 // like the first gesture did, before pilfering. The window configuration has not changed.
3923
3924 // One more tap - DOWN
3925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003926 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003927 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3928 AINPUT_SOURCE_TOUCHSCREEN)
3929 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003930 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003931 .build()));
3932 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3933 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3934 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3935 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3936
3937 // Touch UP on the window
3938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003939 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003940 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3941 AINPUT_SOURCE_TOUCHSCREEN)
3942 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003943 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003944 .build()));
3945 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3946 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3947 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3948 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3949
3950 window->assertNoEvents();
3951 spyWindow->assertNoEvents();
3952}
3953
Garfield Tandf26e862020-07-01 20:18:19 -07003954// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3955// directly in this test.
3956TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003958 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003959 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003960 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003961
3962 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3963
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003964 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003965
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003967 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003968 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3969 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003971 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003972 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003973 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003975 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003976 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3977 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003978 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003979 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003980 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3981 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003982
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003984 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003985 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3986 AINPUT_SOURCE_MOUSE)
3987 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3988 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003989 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003990 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003991 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003992
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003994 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003995 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3996 AINPUT_SOURCE_MOUSE)
3997 .buttonState(0)
3998 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004000 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004001 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004002
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004004 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004005 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4006 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004007 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004008 .build()));
4009 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4010
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004011 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4012 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4013 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004014 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004015 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4016 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004017 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004018 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004019 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004020}
4021
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004022/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004023 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4024 * is generated.
4025 */
4026TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4028 sp<FakeWindowHandle> window =
4029 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4030 window->setFrame(Rect(0, 0, 1200, 800));
4031
4032 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4033
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004034 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004035
4036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004037 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004038 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4039 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004040 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004041 .build()));
4042 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4043
4044 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004045 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004046 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4047}
4048
4049/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004050 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4051 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004052TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4053 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4054 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4056 sp<FakeWindowHandle> window =
4057 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4058 window->setFrame(Rect(0, 0, 1200, 800));
4059
4060 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4061
4062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4063
4064 MotionEventBuilder hoverEnterBuilder =
4065 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4066 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4067 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4069 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4071 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4072 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4073 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4074}
4075
4076/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004077 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4078 */
4079TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4080 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4081 sp<FakeWindowHandle> window =
4082 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4083 window->setFrame(Rect(0, 0, 100, 100));
4084
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004085 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004086
4087 const int32_t mouseDeviceId = 7;
4088 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004089
4090 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4092 .deviceId(mouseDeviceId)
4093 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4094 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004095 window->consumeMotionEvent(
4096 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4097
4098 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4100 .deviceId(touchDeviceId)
4101 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4102 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004103
4104 window->consumeMotionEvent(
4105 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4106 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4107}
4108
4109/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004110 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004111 * The tap causes a HOVER_EXIT event to be generated because the current event
4112 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004113 */
4114TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4116 sp<FakeWindowHandle> window =
4117 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4118 window->setFrame(Rect(0, 0, 100, 100));
4119
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004120 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4122 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4123 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004124 ASSERT_NO_FATAL_FAILURE(
4125 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4126 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004127
4128 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4130 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4131 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004132 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004133 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4134 WithSource(AINPUT_SOURCE_MOUSE))));
4135
4136 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004137 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4138 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4139
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004140 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4141 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4142 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004143 ASSERT_NO_FATAL_FAILURE(
4144 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4145 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4146}
4147
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004148TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4150 sp<FakeWindowHandle> windowDefaultDisplay =
4151 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4152 ADISPLAY_ID_DEFAULT);
4153 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4154 sp<FakeWindowHandle> windowSecondDisplay =
4155 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4156 SECOND_DISPLAY_ID);
4157 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4158
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004159 mDispatcher->onWindowInfosChanged(
4160 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004161
4162 // Set cursor position in window in default display and check that hover enter and move
4163 // events are generated.
4164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004166 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4167 AINPUT_SOURCE_MOUSE)
4168 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004170 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004171 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004172
4173 // Remove all windows in secondary display and check that no event happens on window in
4174 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004175 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4176
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004177 windowDefaultDisplay->assertNoEvents();
4178
4179 // Move cursor position in window in default display and check that only hover move
4180 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004181 mDispatcher->onWindowInfosChanged(
4182 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004184 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004185 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4186 AINPUT_SOURCE_MOUSE)
4187 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004188 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004189 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004190 windowDefaultDisplay->consumeMotionEvent(
4191 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4192 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004193 windowDefaultDisplay->assertNoEvents();
4194}
4195
Garfield Tan00f511d2019-06-12 16:55:40 -07004196TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004198
4199 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004200 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004201 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004202 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004203 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004204 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004205
4206 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4207
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004208 mDispatcher->onWindowInfosChanged(
4209 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004210
4211 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4212 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004214 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004215 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004216 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004217 windowRight->assertNoEvents();
4218}
4219
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004220TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004222 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4223 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004224 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004225
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004226 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004227 setFocusedWindow(window);
4228
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004229 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004230
Prabir Pradhan678438e2023-04-13 19:32:51 +00004231 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004232
4233 // Window should receive key down event.
4234 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4235
4236 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4237 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004238 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004239 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004240 AKEY_EVENT_FLAG_CANCELED);
4241}
4242
4243TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004245 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4246 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004247
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004248 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004249
Prabir Pradhan678438e2023-04-13 19:32:51 +00004250 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4251 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004252
4253 // Window should receive motion down event.
4254 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4255
4256 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4257 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004258 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004259 window->consumeMotionEvent(
4260 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004261}
4262
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004263TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4265 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4266 "Fake Window", ADISPLAY_ID_DEFAULT);
4267
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004268 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004269
4270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4271 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4272 .build());
4273
4274 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4275
4276 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4277 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4278 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4279
4280 // After the device has been reset, a new hovering stream can be sent to the window
4281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4282 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4283 .build());
4284 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4285}
4286
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004287TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004289 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4290 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004291 window->setFocusable(true);
4292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004293 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004294 setFocusedWindow(window);
4295
4296 window->consumeFocusEvent(true);
4297
Prabir Pradhan678438e2023-04-13 19:32:51 +00004298 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004299 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4300 const nsecs_t injectTime = keyArgs.eventTime;
4301 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004302 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004303 // The dispatching time should be always greater than or equal to intercept key timeout.
4304 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4305 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4306 std::chrono::nanoseconds(interceptKeyTimeout).count());
4307}
4308
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004309/**
4310 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4311 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004312TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004314 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4315 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004316 window->setFocusable(true);
4317
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004318 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004319 setFocusedWindow(window);
4320
4321 window->consumeFocusEvent(true);
4322
Prabir Pradhan678438e2023-04-13 19:32:51 +00004323 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004324 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004325
4326 // Set a value that's significantly larger than the default consumption timeout. If the
4327 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4328 mFakePolicy->setInterceptKeyTimeout(600ms);
4329 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4330 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004331 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4332}
4333
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004334/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004335 * Two windows. First is a regular window. Second does not overlap with the first, and has
4336 * WATCH_OUTSIDE_TOUCH.
4337 * Both windows are owned by the same UID.
4338 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4339 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4340 */
4341TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004343 sp<FakeWindowHandle> window =
4344 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004345 window->setFrame(Rect{0, 0, 100, 100});
4346
4347 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004348 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004349 ADISPLAY_ID_DEFAULT);
4350 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4351 outsideWindow->setWatchOutsideTouch(true);
4352 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004353 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004354
4355 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004356 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4357 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4358 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004359 window->consumeMotionDown();
4360 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4361 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4362 outsideWindow->consumeMotionEvent(
4363 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004364
4365 // Ensure outsideWindow doesn't get any more events for the gesture.
4366 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4367 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4368 window->consumeMotionMove();
4369 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004370}
4371
4372/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004373 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4374 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4375 * ACTION_OUTSIDE event is sent per gesture.
4376 */
4377TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4378 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004380 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4381 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004382 window->setWatchOutsideTouch(true);
4383 window->setFrame(Rect{0, 0, 100, 100});
4384 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004385 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4386 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004387 secondWindow->setFrame(Rect{100, 100, 200, 200});
4388 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004389 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4390 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004391 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004392 mDispatcher->onWindowInfosChanged(
4393 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004394
4395 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4397 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4398 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004399 window->assertNoEvents();
4400 secondWindow->assertNoEvents();
4401
4402 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4403 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004404 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4405 ADISPLAY_ID_DEFAULT,
4406 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004407 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4408 window->consumeMotionEvent(
4409 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004410 secondWindow->consumeMotionDown();
4411 thirdWindow->assertNoEvents();
4412
4413 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4414 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004415 mDispatcher->notifyMotion(
4416 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4417 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004418 window->assertNoEvents();
4419 secondWindow->consumeMotionMove();
4420 thirdWindow->consumeMotionDown();
4421}
4422
Prabir Pradhan814fe082022-07-22 20:22:18 +00004423TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004425 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4426 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004427 window->setFocusable(true);
4428
Patrick Williamsd828f302023-04-28 17:52:08 -05004429 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004430 setFocusedWindow(window);
4431
4432 window->consumeFocusEvent(true);
4433
Prabir Pradhan678438e2023-04-13 19:32:51 +00004434 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4435 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4436 mDispatcher->notifyKey(keyDown);
4437 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004438
4439 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4440 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4441
4442 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004443 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004444
4445 window->consumeFocusEvent(false);
4446
Prabir Pradhan678438e2023-04-13 19:32:51 +00004447 mDispatcher->notifyKey(keyDown);
4448 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004449 window->assertNoEvents();
4450}
4451
Arthur Hung96483742022-11-15 03:30:48 +00004452TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4454 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4455 "Fake Window", ADISPLAY_ID_DEFAULT);
4456 // Ensure window is non-split and have some transform.
4457 window->setPreventSplitting(true);
4458 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004460
4461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004462 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004463 {50, 50}))
4464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4465 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4466
4467 const MotionEvent secondFingerDownEvent =
4468 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4469 .displayId(ADISPLAY_ID_DEFAULT)
4470 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004471 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4472 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004473 .build();
4474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004475 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004476 InputEventInjectionSync::WAIT_FOR_RESULT))
4477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4478
4479 const MotionEvent* event = window->consumeMotion();
4480 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4481 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4482 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4483 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4484 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4485}
4486
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004487/**
4488 * Two windows: a splittable and a non-splittable.
4489 * The non-splittable window shouldn't receive any "incomplete" gestures.
4490 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4491 * The second pointer should be dropped because the initial window is splittable, so it won't get
4492 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4493 * "incomplete" gestures.
4494 */
4495TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4496 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4497 sp<FakeWindowHandle> leftWindow =
4498 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4499 ADISPLAY_ID_DEFAULT);
4500 leftWindow->setPreventSplitting(false);
4501 leftWindow->setFrame(Rect(0, 0, 100, 100));
4502 sp<FakeWindowHandle> rightWindow =
4503 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4504 ADISPLAY_ID_DEFAULT);
4505 rightWindow->setPreventSplitting(true);
4506 rightWindow->setFrame(Rect(100, 100, 200, 200));
4507 mDispatcher->onWindowInfosChanged(
4508 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4509
4510 // Touch down on left, splittable window
4511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4512 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4513 .build());
4514 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4515
4516 mDispatcher->notifyMotion(
4517 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4518 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4519 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4520 .build());
4521 leftWindow->assertNoEvents();
4522 rightWindow->assertNoEvents();
4523}
4524
Harry Cuttsb166c002023-05-09 13:06:05 +00004525TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4527 sp<FakeWindowHandle> window =
4528 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4529 window->setFrame(Rect(0, 0, 400, 400));
4530 sp<FakeWindowHandle> trustedOverlay =
4531 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4532 ADISPLAY_ID_DEFAULT);
4533 trustedOverlay->setSpy(true);
4534 trustedOverlay->setTrustedOverlay(true);
4535
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004536 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004537
4538 // Start a three-finger touchpad swipe
4539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4540 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4541 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4542 .build());
4543 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4544 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4545 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4546 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4547 .build());
4548 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4549 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4550 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4551 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4552 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4553 .build());
4554
4555 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4556 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4557 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4558
4559 // Move the swipe a bit
4560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4561 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4562 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4563 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4564 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4565 .build());
4566
4567 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4568
4569 // End the swipe
4570 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4571 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4572 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4573 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4574 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4575 .build());
4576 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4577 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4578 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4579 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4580 .build());
4581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4582 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4583 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4584 .build());
4585
4586 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4587 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4588 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4589
4590 window->assertNoEvents();
4591}
4592
4593TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4595 sp<FakeWindowHandle> window =
4596 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4597 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004598 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004599
4600 // Start a three-finger touchpad swipe
4601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4602 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4603 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4604 .build());
4605 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4606 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4607 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4608 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4609 .build());
4610 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4611 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4612 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4613 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4614 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4615 .build());
4616
4617 // Move the swipe a bit
4618 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4619 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4620 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4621 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4622 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4623 .build());
4624
4625 // End the swipe
4626 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4627 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4628 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4629 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4630 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4631 .build());
4632 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4633 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4634 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4635 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4636 .build());
4637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4638 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4639 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4640 .build());
4641
4642 window->assertNoEvents();
4643}
4644
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004645/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004646 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4647 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004648 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004649 */
4650TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4652 sp<FakeWindowHandle> window =
4653 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4654 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004655 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004656
4657 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4659 .downTime(baseTime + 10)
4660 .eventTime(baseTime + 10)
4661 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4662 .build());
4663
4664 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4665
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004666 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004667 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004668
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004670
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004671 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4672 .downTime(baseTime + 10)
4673 .eventTime(baseTime + 30)
4674 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4675 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4676 .build());
4677
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004678 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4679
4680 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004681 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4682 .downTime(baseTime + 10)
4683 .eventTime(baseTime + 40)
4684 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4685 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4686 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004687
4688 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4689
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4691 .downTime(baseTime + 10)
4692 .eventTime(baseTime + 50)
4693 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4694 .build());
4695
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004696 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4697
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4699 .downTime(baseTime + 60)
4700 .eventTime(baseTime + 60)
4701 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4702 .build());
4703
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004704 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004705}
4706
4707/**
Hu Guo771a7692023-09-17 20:51:08 +08004708 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4709 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4710 * its coordinates should be converted by the transform of the windows of target screen.
4711 */
4712TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4713 // This case will create a window and a spy window on the default display and mirror
4714 // window on the second display. cancel event is sent through spy window pilferPointers
4715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4716
4717 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4718 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4719 spyWindowDefaultDisplay->setTrustedOverlay(true);
4720 spyWindowDefaultDisplay->setSpy(true);
4721
4722 sp<FakeWindowHandle> windowDefaultDisplay =
4723 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4724 ADISPLAY_ID_DEFAULT);
4725 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4726
4727 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4728 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4729
4730 // Add the windows to the dispatcher
4731 mDispatcher->onWindowInfosChanged(
4732 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4733 *windowSecondDisplay->getInfo()},
4734 {},
4735 0,
4736 0});
4737
4738 // Send down to ADISPLAY_ID_DEFAULT
4739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4741 {100, 100}))
4742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4743
4744 spyWindowDefaultDisplay->consumeMotionDown();
4745 windowDefaultDisplay->consumeMotionDown();
4746
4747 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4748
4749 // windowDefaultDisplay gets cancel
4750 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4751 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4752
4753 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4754 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4755 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4756 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4757 EXPECT_EQ(100, event->getX(0));
4758 EXPECT_EQ(100, event->getY(0));
4759}
4760
4761/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004762 * Ensure the correct coordinate spaces are used by InputDispatcher.
4763 *
4764 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4765 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4766 * space.
4767 */
4768class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4769public:
4770 void SetUp() override {
4771 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004772 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004773 }
4774
4775 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4776 gui::DisplayInfo info;
4777 info.displayId = displayId;
4778 info.transform = transform;
4779 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004780 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004781 }
4782
4783 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4784 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004785 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004786 }
4787
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004788 void removeAllWindowsAndDisplays() {
4789 mDisplayInfos.clear();
4790 mWindowInfos.clear();
4791 }
4792
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004793 // Set up a test scenario where the display has a scaled projection and there are two windows
4794 // on the display.
4795 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4796 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4797 // respectively.
4798 ui::Transform displayTransform;
4799 displayTransform.set(2, 0, 0, 4);
4800 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4801
4802 std::shared_ptr<FakeApplicationHandle> application =
4803 std::make_shared<FakeApplicationHandle>();
4804
4805 // Add two windows to the display. Their frames are represented in the display space.
4806 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004807 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4808 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004809 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4810 addWindow(firstWindow);
4811
4812 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004813 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4814 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004815 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4816 addWindow(secondWindow);
4817 return {std::move(firstWindow), std::move(secondWindow)};
4818 }
4819
4820private:
4821 std::vector<gui::DisplayInfo> mDisplayInfos;
4822 std::vector<gui::WindowInfo> mWindowInfos;
4823};
4824
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004825TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004826 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4827 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004828 // selected so that if the hit test was performed with the point and the bounds being in
4829 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004830 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4831 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4832 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004833
4834 firstWindow->consumeMotionDown();
4835 secondWindow->assertNoEvents();
4836}
4837
4838// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4839// the event should be treated as being in the logical display space.
4840TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4841 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4842 // Send down to the first window. The point is represented in the logical display space. The
4843 // point is selected so that if the hit test was done in logical display space, then it would
4844 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004846 PointF{75 * 2, 55 * 4});
4847
4848 firstWindow->consumeMotionDown();
4849 secondWindow->assertNoEvents();
4850}
4851
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004852// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4853// event should be treated as being in the logical display space.
4854TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4855 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4856
4857 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4858 ui::Transform injectedEventTransform;
4859 injectedEventTransform.set(matrix);
4860 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4861 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4862
4863 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4864 .displayId(ADISPLAY_ID_DEFAULT)
4865 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004866 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004867 .x(untransformedPoint.x)
4868 .y(untransformedPoint.y))
4869 .build();
4870 event.transform(matrix);
4871
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004872 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004873 InputEventInjectionSync::WAIT_FOR_RESULT);
4874
4875 firstWindow->consumeMotionDown();
4876 secondWindow->assertNoEvents();
4877}
4878
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004879TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4880 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4881
4882 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004883 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4884 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4885 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004886
4887 firstWindow->assertNoEvents();
4888 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004889 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004890 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4891
4892 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4893 EXPECT_EQ(300, event->getRawX(0));
4894 EXPECT_EQ(880, event->getRawY(0));
4895
4896 // Ensure that the x and y values are in the window's coordinate space.
4897 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4898 // the logical display space. This will be the origin of the window space.
4899 EXPECT_EQ(100, event->getX(0));
4900 EXPECT_EQ(80, event->getY(0));
4901}
4902
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004903TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4904 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4905 // The monitor will always receive events in the logical display's coordinate space, because
4906 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004907 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004908
4909 // Send down to the first window.
4910 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4911 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4912 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4913 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4914
4915 // Second pointer goes down on second window.
4916 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4917 ADISPLAY_ID_DEFAULT,
4918 {PointF{50, 100}, PointF{150, 220}}));
4919 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4920 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4921 {1, PointF{300, 880}}};
4922 monitor.consumeMotionEvent(
4923 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4924
4925 mDispatcher->cancelCurrentTouch();
4926
4927 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4928 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4929 monitor.consumeMotionEvent(
4930 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4931}
4932
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004933TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4934 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4935
4936 // Send down to the first window.
4937 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4938 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4939 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4940
4941 // The pointer is transferred to the second window, and the second window receives it in the
4942 // correct coordinate space.
4943 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4944 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4945 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4946}
4947
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004948TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4949 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4950
4951 // Send hover move to the second window, and ensure it shows up as hover enter.
4952 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4953 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4954 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4955 WithCoords(100, 80), WithRawCoords(300, 880)));
4956
4957 // Touch down at the same location and ensure a hover exit is synthesized.
4958 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4959 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4960 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4961 WithRawCoords(300, 880)));
4962 secondWindow->consumeMotionEvent(
4963 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4964 secondWindow->assertNoEvents();
4965 firstWindow->assertNoEvents();
4966}
4967
Prabir Pradhan453ae732023-10-13 14:30:14 +00004968// Same as above, but while the window is being mirrored.
4969TEST_F(InputDispatcherDisplayProjectionTest,
4970 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4971 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4972
4973 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4974 ui::Transform secondDisplayTransform;
4975 secondDisplayTransform.set(matrix);
4976 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4977
4978 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4979 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4980 addWindow(secondWindowClone);
4981
4982 // Send hover move to the second window, and ensure it shows up as hover enter.
4983 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4984 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4985 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4986 WithCoords(100, 80), WithRawCoords(300, 880)));
4987
4988 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4989 // display.
4990 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4991 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4992 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4993 WithRawCoords(300, 880)));
4994 secondWindow->consumeMotionEvent(
4995 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4996 secondWindow->assertNoEvents();
4997 firstWindow->assertNoEvents();
4998}
4999
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005000TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5001 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5002
5003 // Send hover enter to second window
5004 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5005 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5006 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5007 WithCoords(100, 80), WithRawCoords(300, 880)));
5008
5009 mDispatcher->cancelCurrentTouch();
5010
5011 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5012 WithRawCoords(300, 880)));
5013 secondWindow->assertNoEvents();
5014 firstWindow->assertNoEvents();
5015}
5016
Prabir Pradhan453ae732023-10-13 14:30:14 +00005017// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005018TEST_F(InputDispatcherDisplayProjectionTest,
5019 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5020 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5021
5022 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5023 ui::Transform secondDisplayTransform;
5024 secondDisplayTransform.set(matrix);
5025 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5026
5027 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5028 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5029 addWindow(secondWindowClone);
5030
5031 // Send hover enter to second window
5032 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5033 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5034 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5035 WithCoords(100, 80), WithRawCoords(300, 880),
5036 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5037
5038 mDispatcher->cancelCurrentTouch();
5039
5040 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5041 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5042 WithRawCoords(300, 880),
5043 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5044 secondWindow->assertNoEvents();
5045 firstWindow->assertNoEvents();
5046}
5047
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005048/** Ensure consistent behavior of InputDispatcher in all orientations. */
5049class InputDispatcherDisplayOrientationFixture
5050 : public InputDispatcherDisplayProjectionTest,
5051 public ::testing::WithParamInterface<ui::Rotation> {};
5052
5053// This test verifies the touchable region of a window for all rotations of the display by tapping
5054// in different locations on the display, specifically points close to the four corners of a
5055// window.
5056TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5057 constexpr static int32_t displayWidth = 400;
5058 constexpr static int32_t displayHeight = 800;
5059
5060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5061
5062 const auto rotation = GetParam();
5063
5064 // Set up the display with the specified rotation.
5065 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5066 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5067 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5068 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5069 logicalDisplayWidth, logicalDisplayHeight);
5070 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5071
5072 // Create a window with its bounds determined in the logical display.
5073 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5074 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5075 sp<FakeWindowHandle> window =
5076 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5077 window->setFrame(frameInDisplay, displayTransform);
5078 addWindow(window);
5079
5080 // The following points in logical display space should be inside the window.
5081 static const std::array<vec2, 4> insidePoints{
5082 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5083 for (const auto pointInsideWindow : insidePoints) {
5084 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5085 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005086 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5087 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5088 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005089 window->consumeMotionDown();
5090
Prabir Pradhan678438e2023-04-13 19:32:51 +00005091 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5092 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5093 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005094 window->consumeMotionUp();
5095 }
5096
5097 // The following points in logical display space should be outside the window.
5098 static const std::array<vec2, 5> outsidePoints{
5099 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5100 for (const auto pointOutsideWindow : outsidePoints) {
5101 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5102 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005103 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5104 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5105 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005106
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5109 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005110 }
5111 window->assertNoEvents();
5112}
5113
5114// Run the precision tests for all rotations.
5115INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5116 InputDispatcherDisplayOrientationFixture,
5117 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5118 ui::ROTATION_270),
5119 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5120 return ftl::enum_string(testParamInfo.param);
5121 });
5122
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005123using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5124 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005125
5126class TransferTouchFixture : public InputDispatcherTest,
5127 public ::testing::WithParamInterface<TransferFunction> {};
5128
5129TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005131
5132 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005133 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005134 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5135 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005136 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005137 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005138 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5139 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005140 sp<FakeWindowHandle> wallpaper =
5141 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5142 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005143 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005144 mDispatcher->onWindowInfosChanged(
5145 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005146
5147 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005148 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5149 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005150
Svet Ganov5d3bc372020-01-26 23:11:07 -08005151 // Only the first window should get the down event
5152 firstWindow->consumeMotionDown();
5153 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005154 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005155
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005156 // Transfer touch to the second window
5157 TransferFunction f = GetParam();
5158 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5159 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005160 // The first window gets cancel and the second gets down
5161 firstWindow->consumeMotionCancel();
5162 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005163 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005164
5165 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5167 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005168 // The first window gets no events and the second gets up
5169 firstWindow->assertNoEvents();
5170 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005171 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005172}
5173
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005174/**
5175 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5176 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5177 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5178 * natural to the user.
5179 * In this test, we are sending a pointer to both spy window and first window. We then try to
5180 * transfer touch to the second window. The dispatcher should identify the first window as the
5181 * one that should lose the gesture, and therefore the action should be to move the gesture from
5182 * the first window to the second.
5183 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5184 * the other API, as well.
5185 */
5186TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5188
5189 // Create a couple of windows + a spy window
5190 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005191 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005192 spyWindow->setTrustedOverlay(true);
5193 spyWindow->setSpy(true);
5194 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005195 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005196 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005197 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005198
5199 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005200 mDispatcher->onWindowInfosChanged(
5201 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005202
5203 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005204 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5205 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005206 // Only the first window and spy should get the down event
5207 spyWindow->consumeMotionDown();
5208 firstWindow->consumeMotionDown();
5209
5210 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5211 // if f === 'transferTouch'.
5212 TransferFunction f = GetParam();
5213 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5214 ASSERT_TRUE(success);
5215 // The first window gets cancel and the second gets down
5216 firstWindow->consumeMotionCancel();
5217 secondWindow->consumeMotionDown();
5218
5219 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5221 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005222 // The first window gets no events and the second+spy get up
5223 firstWindow->assertNoEvents();
5224 spyWindow->consumeMotionUp();
5225 secondWindow->consumeMotionUp();
5226}
5227
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005228TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005230
5231 PointF touchPoint = {10, 10};
5232
5233 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005234 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005235 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5236 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005237 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005238 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005239 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5240 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005241 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005242
5243 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005244 mDispatcher->onWindowInfosChanged(
5245 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005246
5247 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005248 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5249 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5250 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005251 // Only the first window should get the down event
5252 firstWindow->consumeMotionDown();
5253 secondWindow->assertNoEvents();
5254
5255 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005256 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5257 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005258 // Only the first window should get the pointer down event
5259 firstWindow->consumeMotionPointerDown(1);
5260 secondWindow->assertNoEvents();
5261
5262 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005263 TransferFunction f = GetParam();
5264 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5265 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005266 // The first window gets cancel and the second gets down and pointer down
5267 firstWindow->consumeMotionCancel();
5268 secondWindow->consumeMotionDown();
5269 secondWindow->consumeMotionPointerDown(1);
5270
5271 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005272 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5273 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005274 // The first window gets nothing and the second gets pointer up
5275 firstWindow->assertNoEvents();
5276 secondWindow->consumeMotionPointerUp(1);
5277
5278 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005279 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5280 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005281 // The first window gets nothing and the second gets up
5282 firstWindow->assertNoEvents();
5283 secondWindow->consumeMotionUp();
5284}
5285
Arthur Hungc539dbb2022-12-08 07:45:36 +00005286TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5288
5289 // Create a couple of windows
5290 sp<FakeWindowHandle> firstWindow =
5291 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5292 ADISPLAY_ID_DEFAULT);
5293 firstWindow->setDupTouchToWallpaper(true);
5294 sp<FakeWindowHandle> secondWindow =
5295 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5296 ADISPLAY_ID_DEFAULT);
5297 secondWindow->setDupTouchToWallpaper(true);
5298
5299 sp<FakeWindowHandle> wallpaper1 =
5300 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5301 wallpaper1->setIsWallpaper(true);
5302
5303 sp<FakeWindowHandle> wallpaper2 =
5304 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5305 wallpaper2->setIsWallpaper(true);
5306 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005307 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5308 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5309 {},
5310 0,
5311 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005312
5313 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005314 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5315 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005316
5317 // Only the first window should get the down event
5318 firstWindow->consumeMotionDown();
5319 secondWindow->assertNoEvents();
5320 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5321 wallpaper2->assertNoEvents();
5322
5323 // Transfer touch focus to the second window
5324 TransferFunction f = GetParam();
5325 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5326 ASSERT_TRUE(success);
5327
5328 // The first window gets cancel and the second gets down
5329 firstWindow->consumeMotionCancel();
5330 secondWindow->consumeMotionDown();
5331 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5332 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5333
5334 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005335 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5336 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005337 // The first window gets no events and the second gets up
5338 firstWindow->assertNoEvents();
5339 secondWindow->consumeMotionUp();
5340 wallpaper1->assertNoEvents();
5341 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5342}
5343
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005344// For the cases of single pointer touch and two pointers non-split touch, the api's
5345// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5346// for the case where there are multiple pointers split across several windows.
5347INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5348 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005349 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5350 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005351 return dispatcher->transferTouch(destChannelToken,
5352 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005353 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005354 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5355 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005356 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005357 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005358 }));
5359
Svet Ganov5d3bc372020-01-26 23:11:07 -08005360TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005362
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005363 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5365 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005366 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005367
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005368 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005369 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5370 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005372
5373 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005374 mDispatcher->onWindowInfosChanged(
5375 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005376
5377 PointF pointInFirst = {300, 200};
5378 PointF pointInSecond = {300, 600};
5379
5380 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005381 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5382 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5383 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005384 // Only the first window should get the down event
5385 firstWindow->consumeMotionDown();
5386 secondWindow->assertNoEvents();
5387
5388 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005389 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5390 ADISPLAY_ID_DEFAULT,
5391 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005392 // The first window gets a move and the second a down
5393 firstWindow->consumeMotionMove();
5394 secondWindow->consumeMotionDown();
5395
5396 // Transfer touch focus to the second window
5397 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5398 // The first window gets cancel and the new gets pointer down (it already saw down)
5399 firstWindow->consumeMotionCancel();
5400 secondWindow->consumeMotionPointerDown(1);
5401
5402 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005403 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5404 ADISPLAY_ID_DEFAULT,
5405 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005406 // The first window gets nothing and the second gets pointer up
5407 firstWindow->assertNoEvents();
5408 secondWindow->consumeMotionPointerUp(1);
5409
5410 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005411 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5412 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005413 // The first window gets nothing and the second gets up
5414 firstWindow->assertNoEvents();
5415 secondWindow->consumeMotionUp();
5416}
5417
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005418// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5419// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5420// touch is not supported, so the touch should continue on those windows and the transferred-to
5421// window should get nothing.
5422TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5424
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005425 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005426 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5427 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005428 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005429
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005430 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005431 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5432 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005433 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005434
5435 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005436 mDispatcher->onWindowInfosChanged(
5437 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005438
5439 PointF pointInFirst = {300, 200};
5440 PointF pointInSecond = {300, 600};
5441
5442 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5444 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5445 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005446 // Only the first window should get the down event
5447 firstWindow->consumeMotionDown();
5448 secondWindow->assertNoEvents();
5449
5450 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005451 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5452 ADISPLAY_ID_DEFAULT,
5453 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005454 // The first window gets a move and the second a down
5455 firstWindow->consumeMotionMove();
5456 secondWindow->consumeMotionDown();
5457
5458 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005459 const bool transferred =
5460 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005461 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5462 ASSERT_FALSE(transferred);
5463 firstWindow->assertNoEvents();
5464 secondWindow->assertNoEvents();
5465
5466 // The rest of the dispatch should proceed as normal
5467 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005468 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5469 ADISPLAY_ID_DEFAULT,
5470 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005471 // The first window gets MOVE and the second gets pointer up
5472 firstWindow->consumeMotionMove();
5473 secondWindow->consumeMotionUp();
5474
5475 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005476 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5477 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005478 // The first window gets nothing and the second gets up
5479 firstWindow->consumeMotionUp();
5480 secondWindow->assertNoEvents();
5481}
5482
Arthur Hungabbb9d82021-09-01 14:52:30 +00005483// This case will create two windows and one mirrored window on the default display and mirror
5484// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5485// the windows info of second display before default display.
5486TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5487 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5488 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005489 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005490 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005491 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005493 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005494
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005495 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005496 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005497
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005498 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005499 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005500
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005501 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005502 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005503
5504 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005505 mDispatcher->onWindowInfosChanged(
5506 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5507 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5508 *secondWindowInPrimary->getInfo()},
5509 {},
5510 0,
5511 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512
5513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005515 {50, 50}))
5516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5517
5518 // Window should receive motion event.
5519 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5520
5521 // Transfer touch focus
5522 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5523 secondWindowInPrimary->getToken()));
5524 // The first window gets cancel.
5525 firstWindowInPrimary->consumeMotionCancel();
5526 secondWindowInPrimary->consumeMotionDown();
5527
5528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005529 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005530 ADISPLAY_ID_DEFAULT, {150, 50}))
5531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5532 firstWindowInPrimary->assertNoEvents();
5533 secondWindowInPrimary->consumeMotionMove();
5534
5535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005536 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005537 {150, 50}))
5538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5539 firstWindowInPrimary->assertNoEvents();
5540 secondWindowInPrimary->consumeMotionUp();
5541}
5542
5543// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5544// 'transferTouch' api.
5545TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5547 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005548 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005549 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005550 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005551 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005552 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005553
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005554 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005555 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005556
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005557 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005558 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005559
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005560 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005561 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005562
5563 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005564 mDispatcher->onWindowInfosChanged(
5565 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5566 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5567 *secondWindowInPrimary->getInfo()},
5568 {},
5569 0,
5570 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005571
5572 // Touch on second display.
5573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005574 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5575 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5577
5578 // Window should receive motion event.
5579 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5580
5581 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005582 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005583
5584 // The first window gets cancel.
5585 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5586 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5587
5588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005589 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005590 SECOND_DISPLAY_ID, {150, 50}))
5591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5592 firstWindowInPrimary->assertNoEvents();
5593 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5594
5595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005596 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5598 firstWindowInPrimary->assertNoEvents();
5599 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5600}
5601
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005602TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005604 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5605 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005606
Vishnu Nair47074b82020-08-14 11:54:47 -07005607 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005608 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005609 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005610
5611 window->consumeFocusEvent(true);
5612
Prabir Pradhan678438e2023-04-13 19:32:51 +00005613 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005614
5615 // Window should receive key down event.
5616 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005617
5618 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005619 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005620 mFakePolicy->assertUserActivityPoked();
5621}
5622
5623TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5625 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5626 "Fake Window", ADISPLAY_ID_DEFAULT);
5627
5628 window->setDisableUserActivity(true);
5629 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005630 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005631 setFocusedWindow(window);
5632
5633 window->consumeFocusEvent(true);
5634
5635 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5636
5637 // Window should receive key down event.
5638 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5639
5640 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005641 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005642 mFakePolicy->assertUserActivityNotPoked();
5643}
5644
5645TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5647 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5648 "Fake Window", ADISPLAY_ID_DEFAULT);
5649
5650 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005651 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005652 setFocusedWindow(window);
5653
5654 window->consumeFocusEvent(true);
5655
5656 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5657 mDispatcher->waitForIdle();
5658
5659 // System key is not passed down
5660 window->assertNoEvents();
5661
5662 // Should have poked user activity
5663 mFakePolicy->assertUserActivityPoked();
5664}
5665
5666TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5668 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5669 "Fake Window", ADISPLAY_ID_DEFAULT);
5670
5671 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005673 setFocusedWindow(window);
5674
5675 window->consumeFocusEvent(true);
5676
5677 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5678 mDispatcher->waitForIdle();
5679
5680 // System key is not passed down
5681 window->assertNoEvents();
5682
5683 // Should have poked user activity
5684 mFakePolicy->assertUserActivityPoked();
5685}
5686
5687TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5689 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5690 "Fake Window", ADISPLAY_ID_DEFAULT);
5691
5692 window->setDisableUserActivity(true);
5693 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005694 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005695 setFocusedWindow(window);
5696
5697 window->consumeFocusEvent(true);
5698
5699 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5700 mDispatcher->waitForIdle();
5701
5702 // System key is not passed down
5703 window->assertNoEvents();
5704
5705 // Should have poked user activity
5706 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005707}
5708
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005709TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5712 "Fake Window", ADISPLAY_ID_DEFAULT);
5713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005715
5716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005717 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005718 ADISPLAY_ID_DEFAULT, {100, 100}))
5719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5720
5721 window->consumeMotionEvent(
5722 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5723
5724 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005725 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005726 mFakePolicy->assertUserActivityPoked();
5727}
5728
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005729TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005731 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5732 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005733
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005734 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005735
Prabir Pradhan678438e2023-04-13 19:32:51 +00005736 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005737 mDispatcher->waitForIdle();
5738
5739 window->assertNoEvents();
5740}
5741
5742// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5743TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005745 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5746 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005747
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005748 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005749
5750 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005751 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005752 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005753 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5754 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005755
5756 // Window should receive only the motion event
5757 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5758 window->assertNoEvents(); // Key event or focus event will not be received
5759}
5760
arthurhungea3f4fc2020-12-21 23:18:53 +08005761TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5763
arthurhungea3f4fc2020-12-21 23:18:53 +08005764 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005765 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5766 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005767 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005768
arthurhungea3f4fc2020-12-21 23:18:53 +08005769 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005770 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5771 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005772 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005773
5774 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005775 mDispatcher->onWindowInfosChanged(
5776 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005777
5778 PointF pointInFirst = {300, 200};
5779 PointF pointInSecond = {300, 600};
5780
5781 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005782 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5783 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5784 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005785 // Only the first window should get the down event
5786 firstWindow->consumeMotionDown();
5787 secondWindow->assertNoEvents();
5788
5789 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005790 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5791 ADISPLAY_ID_DEFAULT,
5792 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005793 // The first window gets a move and the second a down
5794 firstWindow->consumeMotionMove();
5795 secondWindow->consumeMotionDown();
5796
5797 // Send pointer cancel to the second window
5798 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005799 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005800 {pointInFirst, pointInSecond});
5801 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005802 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005803 // The first window gets move and the second gets cancel.
5804 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5805 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5806
5807 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005808 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5809 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005810 // The first window gets up and the second gets nothing.
5811 firstWindow->consumeMotionUp();
5812 secondWindow->assertNoEvents();
5813}
5814
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005815TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5817
5818 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005819 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005821 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5822 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5823 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5824
Harry Cutts33476232023-01-30 19:57:29 +00005825 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005826 window->assertNoEvents();
5827 mDispatcher->waitForIdle();
5828}
5829
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005830using InputDispatcherMonitorTest = InputDispatcherTest;
5831
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005832/**
5833 * Two entities that receive touch: A window, and a global monitor.
5834 * The touch goes to the window, and then the window disappears.
5835 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5836 * for the monitor, as well.
5837 * 1. foregroundWindow
5838 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5839 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005840TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5842 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005843 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005844
Prabir Pradhanfb549072023-10-05 19:17:36 +00005845 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005846
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005850 {100, 200}))
5851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5852
5853 // Both the foreground window and the global monitor should receive the touch down
5854 window->consumeMotionDown();
5855 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5856
5857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005858 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005859 ADISPLAY_ID_DEFAULT, {110, 200}))
5860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5861
5862 window->consumeMotionMove();
5863 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5864
5865 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005866 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005867 window->consumeMotionCancel();
5868 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5869
5870 // If more events come in, there will be no more foreground window to send them to. This will
5871 // cause a cancel for the monitor, as well.
5872 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005873 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005874 ADISPLAY_ID_DEFAULT, {120, 200}))
5875 << "Injection should fail because the window was removed";
5876 window->assertNoEvents();
5877 // Global monitor now gets the cancel
5878 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5879}
5880
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005881TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005883 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5884 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005885 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005886
Prabir Pradhanfb549072023-10-05 19:17:36 +00005887 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005888
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005890 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005892 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005893 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005894}
5895
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005896TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005897 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005898
Chris Yea209fde2020-07-22 13:54:51 -07005899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005900 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5901 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005902 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005903
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005905 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005907 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005908 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005909
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005910 // Pilfer pointers from the monitor.
5911 // This should not do anything and the window should continue to receive events.
5912 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005913
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005915 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005916 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005918
5919 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5920 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005921}
5922
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005923TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005925 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5926 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005927 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005928 window->setWindowOffset(20, 40);
5929 window->setWindowTransform(0, 1, -1, 0);
5930
Prabir Pradhanfb549072023-10-05 19:17:36 +00005931 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005932
5933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005934 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5936 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5937 MotionEvent* event = monitor.consumeMotion();
5938 // Even though window has transform, gesture monitor must not.
5939 ASSERT_EQ(ui::Transform(), event->getTransform());
5940}
5941
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005942TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005944 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005945
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005946 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005947 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005948 << "Injection should fail if there is a monitor, but no touchable window";
5949 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005950}
5951
chaviw81e2bb92019-12-18 15:03:51 -08005952TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005954 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5955 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005956
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005957 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005958
5959 NotifyMotionArgs motionArgs =
5960 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5961 ADISPLAY_ID_DEFAULT);
5962
Prabir Pradhan678438e2023-04-13 19:32:51 +00005963 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005964 // Window should receive motion down event.
5965 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5966
5967 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005968 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005969 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5970 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5971 motionArgs.pointerCoords[0].getX() - 10);
5972
Prabir Pradhan678438e2023-04-13 19:32:51 +00005973 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005974 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005975 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005976}
5977
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005978/**
5979 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5980 * the device default right away. In the test scenario, we check both the default value,
5981 * and the action of enabling / disabling.
5982 */
5983TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005985 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5986 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005987 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005988
5989 // Set focused application.
5990 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005991 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005992
5993 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005994 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005995 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005996 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005997
5998 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005999 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006000 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006001 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006002
6003 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006004 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006005 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006006 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006007 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006008 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006009 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006010 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006011
6012 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006013 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006015 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006016
6017 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006018 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006019 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006020 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006021 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006023 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006024 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006025
6026 window->assertNoEvents();
6027}
6028
Gang Wange9087892020-01-07 12:17:14 -05006029TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006031 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6032 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006033
6034 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006035 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006036
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006037 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006038 setFocusedWindow(window);
6039
Harry Cutts33476232023-01-30 19:57:29 +00006040 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006041
Prabir Pradhan678438e2023-04-13 19:32:51 +00006042 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6043 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006044
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006045 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006046 ASSERT_NE(event, nullptr);
6047
6048 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6049 ASSERT_NE(verified, nullptr);
6050 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6051
6052 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6053 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6054 ASSERT_EQ(keyArgs.source, verified->source);
6055 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6056
6057 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6058
6059 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006060 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006061 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006062 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6063 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6064 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6065 ASSERT_EQ(0, verifiedKey.repeatCount);
6066}
6067
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006068TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006070 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6071 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006072
6073 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6074
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006075 ui::Transform transform;
6076 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6077
6078 gui::DisplayInfo displayInfo;
6079 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6080 displayInfo.transform = transform;
6081
Patrick Williamsd828f302023-04-28 17:52:08 -05006082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006083
Prabir Pradhan678438e2023-04-13 19:32:51 +00006084 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006085 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6086 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006087 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006088
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006089 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006090 ASSERT_NE(event, nullptr);
6091
6092 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6093 ASSERT_NE(verified, nullptr);
6094 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6095
6096 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6097 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6098 EXPECT_EQ(motionArgs.source, verified->source);
6099 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6100
6101 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6102
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006103 const vec2 rawXY =
6104 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6105 motionArgs.pointerCoords[0].getXYValue());
6106 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6107 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006108 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006109 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006110 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006111 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6112 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6113}
6114
chaviw09c8d2d2020-08-24 15:48:26 -07006115/**
6116 * Ensure that separate calls to sign the same data are generating the same key.
6117 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6118 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6119 * tests.
6120 */
6121TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6122 KeyEvent event = getTestKeyEvent();
6123 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6124
6125 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6126 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6127 ASSERT_EQ(hmac1, hmac2);
6128}
6129
6130/**
6131 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6132 */
6133TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6134 KeyEvent event = getTestKeyEvent();
6135 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6136 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6137
6138 verifiedEvent.deviceId += 1;
6139 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6140
6141 verifiedEvent.source += 1;
6142 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6143
6144 verifiedEvent.eventTimeNanos += 1;
6145 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6146
6147 verifiedEvent.displayId += 1;
6148 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6149
6150 verifiedEvent.action += 1;
6151 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6152
6153 verifiedEvent.downTimeNanos += 1;
6154 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6155
6156 verifiedEvent.flags += 1;
6157 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6158
6159 verifiedEvent.keyCode += 1;
6160 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6161
6162 verifiedEvent.scanCode += 1;
6163 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6164
6165 verifiedEvent.metaState += 1;
6166 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6167
6168 verifiedEvent.repeatCount += 1;
6169 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6170}
6171
Vishnu Nair958da932020-08-21 17:12:37 -07006172TEST_F(InputDispatcherTest, SetFocusedWindow) {
6173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6174 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006175 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006176 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006177 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006178 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6179
6180 // Top window is also focusable but is not granted focus.
6181 windowTop->setFocusable(true);
6182 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006183 mDispatcher->onWindowInfosChanged(
6184 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006185 setFocusedWindow(windowSecond);
6186
6187 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006189 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006190
6191 // Focused window should receive event.
6192 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6193 windowTop->assertNoEvents();
6194}
6195
6196TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6198 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006199 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6201
6202 window->setFocusable(true);
6203 // Release channel for window is no longer valid.
6204 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006205 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006206 setFocusedWindow(window);
6207
6208 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006209 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006210
6211 // window channel is invalid, so it should not receive any input event.
6212 window->assertNoEvents();
6213}
6214
6215TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6217 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006218 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006219 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6221
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006222 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006223 setFocusedWindow(window);
6224
6225 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006226 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006227
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006228 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006229 window->assertNoEvents();
6230}
6231
6232TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6234 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006235 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006236 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006237 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006238 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6239
6240 windowTop->setFocusable(true);
6241 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006242 mDispatcher->onWindowInfosChanged(
6243 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006244 setFocusedWindow(windowTop);
6245 windowTop->consumeFocusEvent(true);
6246
Chavi Weingarten847e8512023-03-29 00:26:09 +00006247 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006248 mDispatcher->onWindowInfosChanged(
6249 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006250 windowSecond->consumeFocusEvent(true);
6251 windowTop->consumeFocusEvent(false);
6252
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006254 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006255
6256 // Focused window should receive event.
6257 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6258}
6259
Chavi Weingarten847e8512023-03-29 00:26:09 +00006260TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6262 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006263 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006264 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006265 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006266 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6267
6268 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006269 windowSecond->setFocusable(false);
6270 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006271 mDispatcher->onWindowInfosChanged(
6272 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006273 setFocusedWindow(windowTop);
6274 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006275
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006277 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006278
6279 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006280 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006281 windowSecond->assertNoEvents();
6282}
6283
6284TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6286 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006287 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006288 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006289 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6290 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006291 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6292
6293 window->setFocusable(true);
6294 previousFocusedWindow->setFocusable(true);
6295 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006296 mDispatcher->onWindowInfosChanged(
6297 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006298 setFocusedWindow(previousFocusedWindow);
6299 previousFocusedWindow->consumeFocusEvent(true);
6300
6301 // Requesting focus on invisible window takes focus from currently focused window.
6302 setFocusedWindow(window);
6303 previousFocusedWindow->consumeFocusEvent(false);
6304
6305 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006307 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6308 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006309
6310 // Window does not get focus event or key down.
6311 window->assertNoEvents();
6312
6313 // Window becomes visible.
6314 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006315 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006316
6317 // Window receives focus event.
6318 window->consumeFocusEvent(true);
6319 // Focused window receives key down.
6320 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6321}
6322
Vishnu Nair599f1412021-06-21 10:39:58 -07006323TEST_F(InputDispatcherTest, DisplayRemoved) {
6324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6325 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006326 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006327 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6328
6329 // window is granted focus.
6330 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006332 setFocusedWindow(window);
6333 window->consumeFocusEvent(true);
6334
6335 // When a display is removed window loses focus.
6336 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6337 window->consumeFocusEvent(false);
6338}
6339
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006340/**
6341 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6342 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6343 * of the 'slipperyEnterWindow'.
6344 *
6345 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6346 * a way so that the touched location is no longer covered by the top window.
6347 *
6348 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6349 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6350 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6351 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6352 * with ACTION_DOWN).
6353 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6354 * window moved itself away from the touched location and had Flag::SLIPPERY.
6355 *
6356 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6357 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6358 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6359 *
6360 * In this test, we ensure that the event received by the bottom window has
6361 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6362 */
6363TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006364 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006365 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006366
6367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6368 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6369
6370 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006371 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006372 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006373 // Make sure this one overlaps the bottom window
6374 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6375 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6376 // one. Windows with the same owner are not considered to be occluding each other.
6377 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6378
6379 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006380 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006381 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006383 mDispatcher->onWindowInfosChanged(
6384 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006385
6386 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006387 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6388 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6389 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006390 slipperyExitWindow->consumeMotionDown();
6391 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006392 mDispatcher->onWindowInfosChanged(
6393 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006394
Prabir Pradhan678438e2023-04-13 19:32:51 +00006395 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6396 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6397 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006398
6399 slipperyExitWindow->consumeMotionCancel();
6400
6401 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6402 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6403}
6404
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006405/**
6406 * Two windows, one on the left and another on the right. The left window is slippery. The right
6407 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6408 * touch moves from the left window into the right window, the gesture should continue to go to the
6409 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6410 * reproduces a crash.
6411 */
6412TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6414
6415 sp<FakeWindowHandle> leftSlipperyWindow =
6416 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6417 leftSlipperyWindow->setSlippery(true);
6418 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6419
6420 sp<FakeWindowHandle> rightDropTouchesWindow =
6421 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6422 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6423 rightDropTouchesWindow->setDropInput(true);
6424
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006425 mDispatcher->onWindowInfosChanged(
6426 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006427
6428 // Start touch in the left window
6429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6430 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6431 .build());
6432 leftSlipperyWindow->consumeMotionDown();
6433
6434 // And move it into the right window
6435 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6436 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6437 .build());
6438
6439 // Since the right window isn't eligible to receive input, touch does not slip.
6440 // The left window continues to receive the gesture.
6441 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6442 rightDropTouchesWindow->assertNoEvents();
6443}
6444
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006445/**
6446 * A single window is on screen first. Touch is injected into that window. Next, a second window
6447 * appears. Since the first window is slippery, touch will move from the first window to the second.
6448 */
6449TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6451 sp<FakeWindowHandle> originalWindow =
6452 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6453 originalWindow->setFrame(Rect(0, 0, 200, 200));
6454 originalWindow->setSlippery(true);
6455
6456 sp<FakeWindowHandle> appearingWindow =
6457 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6458 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6459
6460 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6461
6462 // Touch down on the original window
6463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6464 injectMotionEvent(*mDispatcher,
6465 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6466 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6467 .build()));
6468 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6469
6470 // Now, a new window appears. This could be, for example, a notification shade that appears
6471 // after user starts to drag down on the launcher window.
6472 mDispatcher->onWindowInfosChanged(
6473 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6475 injectMotionEvent(*mDispatcher,
6476 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6477 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6478 .build()));
6479 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6480 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6482 injectMotionEvent(*mDispatcher,
6483 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6484 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6485 .build()));
6486 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6487
6488 originalWindow->assertNoEvents();
6489 appearingWindow->assertNoEvents();
6490}
6491
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006492TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006493 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6495
6496 sp<FakeWindowHandle> leftWindow =
6497 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6498 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006499 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006500
6501 sp<FakeWindowHandle> rightSpy =
6502 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6503 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006504 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006505 rightSpy->setSpy(true);
6506 rightSpy->setTrustedOverlay(true);
6507
6508 sp<FakeWindowHandle> rightWindow =
6509 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6510 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006511 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006512
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006513 mDispatcher->onWindowInfosChanged(
6514 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006515
6516 // Touch in the left window
6517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6518 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6519 .build());
6520 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6521 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006522 ASSERT_NO_FATAL_FAILURE(
6523 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006524
6525 // Touch another finger over the right windows
6526 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6527 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6528 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6529 .build());
6530 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6531 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6532 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6533 mDispatcher->waitForIdle();
6534 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006535 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6536 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006537
6538 // Release finger over left window. The UP actions are not treated as device interaction.
6539 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6540 // is part of the UP action, we do not treat this as device interaction.
6541 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6542 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6543 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6544 .build());
6545 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6546 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6547 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6548 mDispatcher->waitForIdle();
6549 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6550
6551 // Move remaining finger
6552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6553 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6554 .build());
6555 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6556 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6557 mDispatcher->waitForIdle();
6558 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006559 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006560
6561 // Release all fingers
6562 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6563 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6564 .build());
6565 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6566 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6567 mDispatcher->waitForIdle();
6568 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6569}
6570
6571TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6573
6574 sp<FakeWindowHandle> window =
6575 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6576 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006577 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006578
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006579 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006580 setFocusedWindow(window);
6581 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6582
6583 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6584 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6585 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006586 ASSERT_NO_FATAL_FAILURE(
6587 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006588
6589 // The UP actions are not treated as device interaction.
6590 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6591 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6592 mDispatcher->waitForIdle();
6593 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6594}
6595
Prabir Pradhan5893d362023-11-17 04:30:40 +00006596TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6598
6599 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6600 ADISPLAY_ID_DEFAULT);
6601 left->setFrame(Rect(0, 0, 100, 100));
6602 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6603 "Right Window", ADISPLAY_ID_DEFAULT);
6604 right->setFrame(Rect(100, 0, 200, 100));
6605 sp<FakeWindowHandle> spy =
6606 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6607 spy->setFrame(Rect(0, 0, 200, 100));
6608 spy->setTrustedOverlay(true);
6609 spy->setSpy(true);
6610
6611 mDispatcher->onWindowInfosChanged(
6612 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6613
6614 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6615 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6616 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6617 mDispatcher->notifyMotion(notifyArgs);
6618
6619 const MotionEvent& leftEnter = left->consumeMotionEvent(
6620 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6621 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6622
6623 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6624 Not(WithEventId(notifyArgs.id)),
6625 Not(WithEventId(leftEnter.getId())),
6626 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6627
6628 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6629 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6630 {PointF{150, 50}});
6631 mDispatcher->notifyMotion(notifyArgs);
6632
6633 const MotionEvent& leftExit = left->consumeMotionEvent(
6634 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6635 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6636
6637 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6638 Not(WithEventId(notifyArgs.id)),
6639 Not(WithEventId(leftExit.getId())),
6640 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6641
6642 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6643}
6644
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006645class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6646protected:
6647 std::shared_ptr<FakeApplicationHandle> mApp;
6648 sp<FakeWindowHandle> mWindow;
6649
6650 virtual void SetUp() override {
6651 InputDispatcherTest::SetUp();
6652
6653 mApp = std::make_shared<FakeApplicationHandle>();
6654
6655 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6656 mWindow->setFrame(Rect(0, 0, 100, 100));
6657
6658 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6659 setFocusedWindow(mWindow);
6660 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6661 }
6662
6663 void setFallback(int32_t keycode) {
6664 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6665 return KeyEventBuilder(event).keyCode(keycode).build();
6666 });
6667 }
6668
6669 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6670 KeyEvent* event = mWindow->consumeKey(handled);
6671 ASSERT_NE(event, nullptr) << "Did not receive key event";
6672 ASSERT_THAT(*event, matcher);
6673 }
6674};
6675
6676TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6677 mDispatcher->notifyKey(
6678 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6679 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6680 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6681}
6682
6683TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6684 mDispatcher->notifyKey(
6685 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6686 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6687 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6688}
6689
6690TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6691 mDispatcher->notifyKey(
6692 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6693
6694 // Do not handle this key event.
6695 consumeKey(/*handled=*/false,
6696 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6697 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6698
6699 // Since the policy did not request any fallback to be generated, ensure there are no events.
6700 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6701}
6702
6703TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6704 setFallback(AKEYCODE_B);
6705 mDispatcher->notifyKey(
6706 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6707
6708 // Do not handle this key event.
6709 consumeKey(/*handled=*/false,
6710 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6711
6712 // Since the key was not handled, ensure the fallback event was dispatched instead.
6713 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6714 consumeKey(/*handled=*/true,
6715 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6716 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6717
6718 // Release the original key, and ensure the fallback key is also released.
6719 mDispatcher->notifyKey(
6720 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6721 consumeKey(/*handled=*/false,
6722 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6723 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6724 consumeKey(/*handled=*/true,
6725 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6726 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6727
6728 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6729 mWindow->assertNoEvents();
6730}
6731
6732TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6733 setFallback(AKEYCODE_B);
6734 mDispatcher->notifyKey(
6735 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6736
6737 // Do not handle this key event, but handle the fallback.
6738 consumeKey(/*handled=*/false,
6739 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6740 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6741 consumeKey(/*handled=*/true,
6742 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6743 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6744
6745 // Release the original key, and ensure the fallback key is also released.
6746 mDispatcher->notifyKey(
6747 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6748 // But this time, the app handles the original key.
6749 consumeKey(/*handled=*/true,
6750 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6751 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6752 // Ensure the fallback key is canceled.
6753 consumeKey(/*handled=*/true,
6754 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6755 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6756
6757 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6758 mWindow->assertNoEvents();
6759}
6760
6761TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6762 setFallback(AKEYCODE_B);
6763 mDispatcher->notifyKey(
6764 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6765
6766 // Do not handle this key event.
6767 consumeKey(/*handled=*/false,
6768 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6769 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6770 // App does not handle the fallback either, so ensure another fallback is not generated.
6771 setFallback(AKEYCODE_C);
6772 consumeKey(/*handled=*/false,
6773 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6774 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6775
6776 // Release the original key, and ensure the fallback key is also released.
6777 setFallback(AKEYCODE_B);
6778 mDispatcher->notifyKey(
6779 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6780 consumeKey(/*handled=*/false,
6781 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6782 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6783 consumeKey(/*handled=*/false,
6784 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6785 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6786
6787 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6788 mWindow->assertNoEvents();
6789}
6790
6791TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6792 setFallback(AKEYCODE_B);
6793 mDispatcher->notifyKey(
6794 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6795
6796 // Do not handle this key event, so fallback is generated.
6797 consumeKey(/*handled=*/false,
6798 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6799 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6800 consumeKey(/*handled=*/true,
6801 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6802 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6803
6804 // Release the original key, but assume the policy is misbehaving and it
6805 // generates an inconsistent fallback to the one from the DOWN event.
6806 setFallback(AKEYCODE_C);
6807 mDispatcher->notifyKey(
6808 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6809 consumeKey(/*handled=*/false,
6810 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6811 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6812 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6813 consumeKey(/*handled=*/true,
6814 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6815 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6816
6817 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6818 mWindow->assertNoEvents();
6819}
6820
6821TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6822 setFallback(AKEYCODE_B);
6823 mDispatcher->notifyKey(
6824 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6825
6826 // Do not handle this key event, so fallback is generated.
6827 consumeKey(/*handled=*/false,
6828 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6829 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6830 consumeKey(/*handled=*/true,
6831 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6832 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6833
6834 // The original key is canceled.
6835 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6836 .keyCode(AKEYCODE_A)
6837 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6838 .build());
6839 consumeKey(/*handled=*/false,
6840 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6841 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6842 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6843 // Ensure the fallback key is also canceled due to the original key being canceled.
6844 consumeKey(/*handled=*/true,
6845 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6846 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6847
6848 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6849 mWindow->assertNoEvents();
6850}
6851
Garfield Tan1c7bc862020-01-28 13:24:04 -08006852class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6853protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006854 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6855 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006856
Chris Yea209fde2020-07-22 13:54:51 -07006857 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006858 sp<FakeWindowHandle> mWindow;
6859
6860 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006861 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006862 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006863 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006864 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006865 ASSERT_EQ(OK, mDispatcher->start());
6866
6867 setUpWindow();
6868 }
6869
6870 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006871 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006872 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006873
Vishnu Nair47074b82020-08-14 11:54:47 -07006874 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006875 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006876 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006877 mWindow->consumeFocusEvent(true);
6878 }
6879
Chris Ye2ad95392020-09-01 13:44:44 -07006880 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006881 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006882 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006883 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006884 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006885
6886 // Window should receive key down event.
6887 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6888 }
6889
6890 void expectKeyRepeatOnce(int32_t repeatCount) {
6891 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006892 mWindow->consumeKeyEvent(
6893 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006894 }
6895
Chris Ye2ad95392020-09-01 13:44:44 -07006896 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006897 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006898 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006899 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006900 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006901
6902 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006903 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006904 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006905 }
6906};
6907
6908TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006909 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006910 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6911 expectKeyRepeatOnce(repeatCount);
6912 }
6913}
6914
6915TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006916 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006917 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6918 expectKeyRepeatOnce(repeatCount);
6919 }
Harry Cutts33476232023-01-30 19:57:29 +00006920 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006921 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006922 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6923 expectKeyRepeatOnce(repeatCount);
6924 }
6925}
6926
6927TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006928 sendAndConsumeKeyDown(/*deviceId=*/1);
6929 expectKeyRepeatOnce(/*repeatCount=*/1);
6930 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006931 mWindow->assertNoEvents();
6932}
6933
6934TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006935 sendAndConsumeKeyDown(/*deviceId=*/1);
6936 expectKeyRepeatOnce(/*repeatCount=*/1);
6937 sendAndConsumeKeyDown(/*deviceId=*/2);
6938 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006939 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006940 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006941 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006942 expectKeyRepeatOnce(/*repeatCount=*/2);
6943 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006944 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006945 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006946 mWindow->assertNoEvents();
6947}
6948
6949TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006950 sendAndConsumeKeyDown(/*deviceId=*/1);
6951 expectKeyRepeatOnce(/*repeatCount=*/1);
6952 sendAndConsumeKeyDown(/*deviceId=*/2);
6953 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006954 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006955 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006956 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006957 mWindow->assertNoEvents();
6958}
6959
liushenxiang42232912021-05-21 20:24:09 +08006960TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6961 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006962 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006963 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006964 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6965 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6966 mWindow->assertNoEvents();
6967}
6968
Garfield Tan1c7bc862020-01-28 13:24:04 -08006969TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006970 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006971 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006972 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006973 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006974 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6975 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6976 IdGenerator::getSource(repeatEvent->getId()));
6977 }
6978}
6979
6980TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006981 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006982 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006983
6984 std::unordered_set<int32_t> idSet;
6985 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006986 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006987 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6988 int32_t id = repeatEvent->getId();
6989 EXPECT_EQ(idSet.end(), idSet.find(id));
6990 idSet.insert(id);
6991 }
6992}
6993
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006994/* Test InputDispatcher for MultiDisplay */
6995class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6996public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006997 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006998 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006999
Chris Yea209fde2020-07-22 13:54:51 -07007000 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007001 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007002 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007003
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007004 // Set focus window for primary display, but focused display would be second one.
7005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007006 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007007 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7008
Vishnu Nair958da932020-08-21 17:12:37 -07007009 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007010 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007011
Chris Yea209fde2020-07-22 13:54:51 -07007012 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007013 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007014 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007015 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007016 // Set focus display to second one.
7017 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7018 // Set focus window for second display.
7019 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007020 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007021 mDispatcher->onWindowInfosChanged(
7022 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007023 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007024 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007025 }
7026
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007027 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007028 InputDispatcherTest::TearDown();
7029
Chris Yea209fde2020-07-22 13:54:51 -07007030 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007031 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007032 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007033 windowInSecondary.clear();
7034 }
7035
7036protected:
Chris Yea209fde2020-07-22 13:54:51 -07007037 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007038 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007039 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007040 sp<FakeWindowHandle> windowInSecondary;
7041};
7042
7043TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7044 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007046 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007048 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007049 windowInSecondary->assertNoEvents();
7050
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007051 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007053 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007055 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007056 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007057}
7058
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007059TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007060 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007062 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007064 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007065 windowInSecondary->assertNoEvents();
7066
7067 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007069 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007070 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007071 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007072
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007073 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007074 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007075
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007076 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007077 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007078 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007079
7080 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007081 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007082 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007083 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007084 windowInSecondary->assertNoEvents();
7085}
7086
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007087// Test per-display input monitors for motion event.
7088TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007089 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007090 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007091 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007092 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007093
7094 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007096 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007098 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007099 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007100 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007101 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007102
7103 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007105 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007107 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007108 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007109 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007110 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007111
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007112 // Lift up the touch from the second display
7113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007114 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7116 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7117 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7118
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007119 // Test inject a non-pointer motion event.
7120 // If specific a display, it will dispatch to the focused window of particular display,
7121 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007123 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007125 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007126 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007127 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007128 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007129}
7130
7131// Test per-display input monitors for key event.
7132TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007133 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007134 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007135 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007136 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007137 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007138
7139 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007141 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007142 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007143 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007144 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007145 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007146}
7147
Vishnu Nair958da932020-08-21 17:12:37 -07007148TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7149 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007150 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007151 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007152 mDispatcher->onWindowInfosChanged(
7153 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7154 *windowInSecondary->getInfo()},
7155 {},
7156 0,
7157 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007158 setFocusedWindow(secondWindowInPrimary);
7159 windowInPrimary->consumeFocusEvent(false);
7160 secondWindowInPrimary->consumeFocusEvent(true);
7161
7162 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7164 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007165 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007166 windowInPrimary->assertNoEvents();
7167 windowInSecondary->assertNoEvents();
7168 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7169}
7170
Arthur Hungdfd528e2021-12-08 13:23:04 +00007171TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7172 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007173 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007174 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007175 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007176
7177 // Test touch down on primary display.
7178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007179 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7181 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7182 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7183
7184 // Test touch down on second display.
7185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007186 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7188 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7189 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7190
7191 // Trigger cancel touch.
7192 mDispatcher->cancelCurrentTouch();
7193 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7194 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7195 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7196 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7197
7198 // Test inject a move motion event, no window/monitor should receive the event.
7199 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007200 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007201 ADISPLAY_ID_DEFAULT, {110, 200}))
7202 << "Inject motion event should return InputEventInjectionResult::FAILED";
7203 windowInPrimary->assertNoEvents();
7204 monitorInPrimary.assertNoEvents();
7205
7206 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007207 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007208 SECOND_DISPLAY_ID, {110, 200}))
7209 << "Inject motion event should return InputEventInjectionResult::FAILED";
7210 windowInSecondary->assertNoEvents();
7211 monitorInSecondary.assertNoEvents();
7212}
7213
Jackal Guof9696682018-10-05 12:23:23 +08007214class InputFilterTest : public InputDispatcherTest {
7215protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007216 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7217 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007218 NotifyMotionArgs motionArgs;
7219
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007220 motionArgs =
7221 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007222 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007223 motionArgs =
7224 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007225 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007226 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007227 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007228 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007229 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007230 } else {
7231 mFakePolicy->assertFilterInputEventWasNotCalled();
7232 }
7233 }
7234
7235 void testNotifyKey(bool expectToBeFiltered) {
7236 NotifyKeyArgs keyArgs;
7237
7238 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007239 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007240 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007241 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007242 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007243
7244 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007245 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007246 } else {
7247 mFakePolicy->assertFilterInputEventWasNotCalled();
7248 }
7249 }
7250};
7251
7252// Test InputFilter for MotionEvent
7253TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7254 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007255 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7256 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007257
7258 // Enable InputFilter
7259 mDispatcher->setInputFilterEnabled(true);
7260 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007261 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7262 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007263
7264 // Disable InputFilter
7265 mDispatcher->setInputFilterEnabled(false);
7266 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007267 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7268 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007269}
7270
7271// Test InputFilter for KeyEvent
7272TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7273 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007274 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007275
7276 // Enable InputFilter
7277 mDispatcher->setInputFilterEnabled(true);
7278 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007279 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007280
7281 // Disable InputFilter
7282 mDispatcher->setInputFilterEnabled(false);
7283 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007284 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007285}
7286
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007287// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7288// logical display coordinate space.
7289TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7290 ui::Transform firstDisplayTransform;
7291 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7292 ui::Transform secondDisplayTransform;
7293 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7294
7295 std::vector<gui::DisplayInfo> displayInfos(2);
7296 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7297 displayInfos[0].transform = firstDisplayTransform;
7298 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7299 displayInfos[1].transform = secondDisplayTransform;
7300
Patrick Williamsd828f302023-04-28 17:52:08 -05007301 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007302
7303 // Enable InputFilter
7304 mDispatcher->setInputFilterEnabled(true);
7305
7306 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007307 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7308 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007309}
7310
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007311class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7312protected:
7313 virtual void SetUp() override {
7314 InputDispatcherTest::SetUp();
7315
7316 /**
7317 * We don't need to enable input filter to test the injected event policy, but we enabled it
7318 * here to make the tests more realistic, since this policy only matters when inputfilter is
7319 * on.
7320 */
7321 mDispatcher->setInputFilterEnabled(true);
7322
7323 std::shared_ptr<InputApplicationHandle> application =
7324 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007325 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7326 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007327
7328 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7329 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007330 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007331 setFocusedWindow(mWindow);
7332 mWindow->consumeFocusEvent(true);
7333 }
7334
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007335 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7336 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007337 KeyEvent event;
7338
7339 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7340 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7341 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007342 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007343 const int32_t additionalPolicyFlags =
7344 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007346 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007347 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007348 policyFlags | additionalPolicyFlags));
7349
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007350 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007351 }
7352
7353 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7354 int32_t flags) {
7355 MotionEvent event;
7356 PointerProperties pointerProperties[1];
7357 PointerCoords pointerCoords[1];
7358 pointerProperties[0].clear();
7359 pointerProperties[0].id = 0;
7360 pointerCoords[0].clear();
7361 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7362 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7363
7364 ui::Transform identityTransform;
7365 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7366 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7367 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7368 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7369 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007370 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007371 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007372 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007373
7374 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007376 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007377 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007378 policyFlags | additionalPolicyFlags));
7379
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007380 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007381 }
7382
7383private:
7384 sp<FakeWindowHandle> mWindow;
7385};
7386
7387TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007388 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7389 // filter. Without it, the event will no different from a regularly injected event, and the
7390 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007391 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7392 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007393}
7394
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007395TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007396 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007397 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007398 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7399}
7400
7401TEST_F(InputFilterInjectionPolicyTest,
7402 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7403 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007404 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007405 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007406}
7407
7408TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007409 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7410 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007411}
7412
chaviwfd6d3512019-03-25 13:23:49 -07007413class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007414 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007415 InputDispatcherTest::SetUp();
7416
Chris Yea209fde2020-07-22 13:54:51 -07007417 std::shared_ptr<FakeApplicationHandle> application =
7418 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007419 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007420 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007421 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007422
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007423 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007424 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007425 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007426
7427 // Set focused application.
7428 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007429 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007430
7431 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007432 mDispatcher->onWindowInfosChanged(
7433 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007434 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007435 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007436 }
7437
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007438 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007439 InputDispatcherTest::TearDown();
7440
7441 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007442 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007443 }
7444
7445protected:
7446 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007447 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007448 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007449};
7450
7451// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7452// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7453// the onPointerDownOutsideFocus callback.
7454TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007456 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007457 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007458 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007459 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007460
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007461 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007462 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7463}
7464
7465// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7466// DOWN on the window that doesn't have focus. Ensure no window received the
7467// onPointerDownOutsideFocus callback.
7468TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007470 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7471 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007473 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007474
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007475 ASSERT_TRUE(mDispatcher->waitForIdle());
7476 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007477}
7478
7479// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7480// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7481TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007483 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007484 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007485 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007486
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007487 ASSERT_TRUE(mDispatcher->waitForIdle());
7488 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007489}
7490
7491// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7492// DOWN on the window that already has focus. Ensure no window received the
7493// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007494TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007496 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007497 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007498 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007499 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007500
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007501 ASSERT_TRUE(mDispatcher->waitForIdle());
7502 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007503}
7504
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007505// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7506// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7507TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7508 const MotionEvent event =
7509 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7510 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007511 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007512 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7513 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7516 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7517
7518 ASSERT_TRUE(mDispatcher->waitForIdle());
7519 mFakePolicy->assertOnPointerDownWasNotCalled();
7520 // Ensure that the unfocused window did not receive any FOCUS events.
7521 mUnfocusedWindow->assertNoEvents();
7522}
7523
chaviwaf87b3e2019-10-01 16:59:28 -07007524// These tests ensures we can send touch events to a single client when there are multiple input
7525// windows that point to the same client token.
7526class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7527 virtual void SetUp() override {
7528 InputDispatcherTest::SetUp();
7529
Chris Yea209fde2020-07-22 13:54:51 -07007530 std::shared_ptr<FakeApplicationHandle> application =
7531 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007532 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7533 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007534 mWindow1->setFrame(Rect(0, 0, 100, 100));
7535
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007536 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7537 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007538 mWindow2->setFrame(Rect(100, 100, 200, 200));
7539
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007540 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007541 }
7542
7543protected:
7544 sp<FakeWindowHandle> mWindow1;
7545 sp<FakeWindowHandle> mWindow2;
7546
7547 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007548 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007549 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7550 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007551 }
7552
7553 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7554 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007555 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007556 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007558 ASSERT_NE(nullptr, motionEvent)
7559 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007560
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007561 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007562 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007563
7564 for (size_t i = 0; i < points.size(); i++) {
7565 float expectedX = points[i].x;
7566 float expectedY = points[i].y;
7567
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007568 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007569 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007570 << ", got " << motionEvent->getX(i);
7571 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007572 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007573 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007574 }
7575 }
chaviw9eaa22c2020-07-01 16:21:27 -07007576
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007577 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007578 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007579 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7580 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007581
7582 // Always consume from window1 since it's the window that has the InputReceiver
7583 consumeMotionEvent(mWindow1, action, expectedPoints);
7584 }
chaviwaf87b3e2019-10-01 16:59:28 -07007585};
7586
7587TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7588 // Touch Window 1
7589 PointF touchedPoint = {10, 10};
7590 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007591 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007592
7593 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007594 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007595
7596 // Touch Window 2
7597 touchedPoint = {150, 150};
7598 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007599 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007600}
7601
chaviw9eaa22c2020-07-01 16:21:27 -07007602TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7603 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007604 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007605 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007606
7607 // Touch Window 1
7608 PointF touchedPoint = {10, 10};
7609 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007610 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007611 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007612 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007613
7614 // Touch Window 2
7615 touchedPoint = {150, 150};
7616 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007617 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7618 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007619
chaviw9eaa22c2020-07-01 16:21:27 -07007620 // Update the transform so rotation is set
7621 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007622 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007623 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7624 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007625}
7626
chaviw9eaa22c2020-07-01 16:21:27 -07007627TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007628 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007629 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007630
7631 // Touch Window 1
7632 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7633 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007634 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007635
7636 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007637 touchedPoints.push_back(PointF{150, 150});
7638 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007639 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007640
chaviw9eaa22c2020-07-01 16:21:27 -07007641 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007642 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007643 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007644
chaviw9eaa22c2020-07-01 16:21:27 -07007645 // Update the transform so rotation is set for Window 2
7646 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007647 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007648 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007649 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007650}
7651
chaviw9eaa22c2020-07-01 16:21:27 -07007652TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007653 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007654 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007655
7656 // Touch Window 1
7657 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7658 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007659 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007660
7661 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007662 touchedPoints.push_back(PointF{150, 150});
7663 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007664
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007665 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007666
7667 // Move both windows
7668 touchedPoints = {{20, 20}, {175, 175}};
7669 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7670 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7671
chaviw9eaa22c2020-07-01 16:21:27 -07007672 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007673
chaviw9eaa22c2020-07-01 16:21:27 -07007674 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007675 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007676 expectedPoints.pop_back();
7677
7678 // Touch Window 2
7679 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007680 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007681 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007682 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007683
7684 // Move both windows
7685 touchedPoints = {{20, 20}, {175, 175}};
7686 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7687 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7688
7689 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007690}
7691
7692TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7693 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007694 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007695
7696 // Touch Window 1
7697 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7698 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007699 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007700
7701 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007702 touchedPoints.push_back(PointF{150, 150});
7703 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007704
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007705 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007706
7707 // Move both windows
7708 touchedPoints = {{20, 20}, {175, 175}};
7709 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7710 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7711
chaviw9eaa22c2020-07-01 16:21:27 -07007712 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007713}
7714
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007715/**
7716 * When one of the windows is slippery, the touch should not slip into the other window with the
7717 * same input channel.
7718 */
7719TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7720 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007721 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007722
7723 // Touch down in window 1
7724 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7725 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7726 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7727
7728 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7729 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7730 // getting generated.
7731 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7732 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7733
7734 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7735}
7736
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007737/**
7738 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7739 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7740 * that the pointer is hovering over may have a different transform.
7741 */
7742TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007743 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007744
7745 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7747 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7748 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007749 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7750 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007751 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7753 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7754 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007755 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7756 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7757 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7758}
7759
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007760class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7761 virtual void SetUp() override {
7762 InputDispatcherTest::SetUp();
7763
Chris Yea209fde2020-07-22 13:54:51 -07007764 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007765 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007766 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7767 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007768 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007769 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007770 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007771
7772 // Set focused application.
7773 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007775 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007776 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007777 mWindow->consumeFocusEvent(true);
7778 }
7779
7780 virtual void TearDown() override {
7781 InputDispatcherTest::TearDown();
7782 mWindow.clear();
7783 }
7784
7785protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007786 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007787 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007788 sp<FakeWindowHandle> mWindow;
7789 static constexpr PointF WINDOW_LOCATION = {20, 20};
7790
7791 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007792 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7793 .x(WINDOW_LOCATION.x)
7794 .y(WINDOW_LOCATION.y);
7795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7796 .pointer(touchingPointer)
7797 .build());
7798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7799 .pointer(touchingPointer)
7800 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007801 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007802
7803 sp<FakeWindowHandle> addSpyWindow() {
7804 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007805 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007806 spy->setTrustedOverlay(true);
7807 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007808 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007809 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007810 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007811 return spy;
7812 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007813};
7814
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007815// Send a tap and respond, which should not cause an ANR.
7816TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7817 tapOnWindow();
7818 mWindow->consumeMotionDown();
7819 mWindow->consumeMotionUp();
7820 ASSERT_TRUE(mDispatcher->waitForIdle());
7821 mFakePolicy->assertNotifyAnrWasNotCalled();
7822}
7823
7824// Send a regular key and respond, which should not cause an ANR.
7825TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007827 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7828 ASSERT_TRUE(mDispatcher->waitForIdle());
7829 mFakePolicy->assertNotifyAnrWasNotCalled();
7830}
7831
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007832TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7833 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007834 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007835 mWindow->consumeFocusEvent(false);
7836
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007837 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007838 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7839 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007840 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007842 // Key will not go to window because we have no focused window.
7843 // The 'no focused window' ANR timer should start instead.
7844
7845 // Now, the focused application goes away.
7846 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7847 // The key should get dropped and there should be no ANR.
7848
7849 ASSERT_TRUE(mDispatcher->waitForIdle());
7850 mFakePolicy->assertNotifyAnrWasNotCalled();
7851}
7852
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007853// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007854// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7855// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007856TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007859 WINDOW_LOCATION));
7860
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007861 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7862 ASSERT_TRUE(sequenceNum);
7863 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007864 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007865
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007866 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007867 mWindow->consumeMotionEvent(
7868 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007869 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007870 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007871}
7872
7873// Send a key to the app and have the app not respond right away.
7874TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7875 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007877 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7878 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007879 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007880 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007881 ASSERT_TRUE(mDispatcher->waitForIdle());
7882}
7883
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007884// We have a focused application, but no focused window
7885TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007886 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007887 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888 mWindow->consumeFocusEvent(false);
7889
7890 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007892 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007893 WINDOW_LOCATION));
7894 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7895 mDispatcher->waitForIdle();
7896 mFakePolicy->assertNotifyAnrWasNotCalled();
7897
7898 // Once a focused event arrives, we get an ANR for this application
7899 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7900 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007901 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007902 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007903 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007904 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007905 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007906 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007907 ASSERT_TRUE(mDispatcher->waitForIdle());
7908}
7909
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007910/**
7911 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7912 * there will not be an ANR.
7913 */
7914TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7915 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007916 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007917 mWindow->consumeFocusEvent(false);
7918
7919 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007920 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7921 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007922 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7923 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7924
7925 // Define a valid key down event that is stale (too old).
7926 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007927 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007928 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007929
7930 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7931
7932 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007933 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007934 InputEventInjectionSync::WAIT_FOR_RESULT,
7935 INJECT_EVENT_TIMEOUT, policyFlags);
7936 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7937 << "Injection should fail because the event is stale";
7938
7939 ASSERT_TRUE(mDispatcher->waitForIdle());
7940 mFakePolicy->assertNotifyAnrWasNotCalled();
7941 mWindow->assertNoEvents();
7942}
7943
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007944// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007945// Make sure that we don't notify policy twice about the same ANR.
7946TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007947 const std::chrono::duration appTimeout = 400ms;
7948 mApplication->setDispatchingTimeout(appTimeout);
7949 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7950
Vishnu Nair47074b82020-08-14 11:54:47 -07007951 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007952 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007953 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007954
7955 // Once a focused event arrives, we get an ANR for this application
7956 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7957 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007958 const std::chrono::duration eventInjectionTimeout = 100ms;
7959 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007960 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007961 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007962 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7963 /*allowKeyRepeat=*/false);
7964 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7965 << "result=" << ftl::enum_string(result);
7966 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7967 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7968 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7969 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007970
Vishnu Naire4df8752022-09-08 09:17:55 -07007971 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007972 // ANR should not be raised again. It is up to policy to do that if it desires.
7973 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007974
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007975 // If we now get a focused window, the ANR should stop, but the policy handles that via
7976 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007977 ASSERT_TRUE(mDispatcher->waitForIdle());
7978}
7979
7980// We have a focused application, but no focused window
7981TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007982 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007983 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007984 mWindow->consumeFocusEvent(false);
7985
7986 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007987 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007988
Vishnu Naire4df8752022-09-08 09:17:55 -07007989 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7990 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991
7992 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007993 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007994 ASSERT_TRUE(mDispatcher->waitForIdle());
7995 mWindow->assertNoEvents();
7996}
7997
7998/**
7999 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8000 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8001 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8002 * the ANR mechanism should still work.
8003 *
8004 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8005 * DOWN event, while not responding on the second one.
8006 */
8007TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8008 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008009 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008010 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8011 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8012 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008013 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008014
8015 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008016 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8018 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8019 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008020 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021
8022 // We have now sent down and up. Let's consume first event and then ANR on the second.
8023 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8024 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008025 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026}
8027
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008028// A spy window can receive an ANR
8029TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8030 sp<FakeWindowHandle> spy = addSpyWindow();
8031
8032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008033 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008034 WINDOW_LOCATION));
8035 mWindow->consumeMotionDown();
8036
8037 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8038 ASSERT_TRUE(sequenceNum);
8039 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008040 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008041
8042 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008043 spy->consumeMotionEvent(
8044 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008045 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008046 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008047}
8048
8049// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008050// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008051TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8052 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008053
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008055 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008056 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008058
8059 // Stuck on the ACTION_UP
8060 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008061 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008062
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008063 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008064 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008065 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8066 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008067
8068 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8069 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008070 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008071 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008072 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008073}
8074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008075// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008076// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008077TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8078 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008079
8080 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008081 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8082 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008083
8084 mWindow->consumeMotionDown();
8085 // Stuck on the ACTION_UP
8086 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008087 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008088
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008089 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008091 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8092 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008093
8094 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8095 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008096 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008097 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008098 spy->assertNoEvents();
8099}
8100
8101TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008102 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008103
Prabir Pradhanfb549072023-10-05 19:17:36 +00008104 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008105
8106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008107 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008108 WINDOW_LOCATION));
8109
8110 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8111 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8112 ASSERT_TRUE(consumeSeq);
8113
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008114 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8115 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008116
8117 monitor.finishEvent(*consumeSeq);
8118 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8119
8120 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008121 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008122}
8123
8124// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8125// process events, you don't get an anr. When the window later becomes unresponsive again, you
8126// get an ANR again.
8127// 1. tap -> block on ACTION_UP -> receive ANR
8128// 2. consume all pending events (= queue becomes healthy again)
8129// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8130TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8131 tapOnWindow();
8132
8133 mWindow->consumeMotionDown();
8134 // Block on ACTION_UP
8135 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008136 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008137 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8138 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008139 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008140 mWindow->assertNoEvents();
8141
8142 tapOnWindow();
8143 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008144 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008145 mWindow->consumeMotionUp();
8146
8147 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008148 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008149 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008150 mWindow->assertNoEvents();
8151}
8152
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008153// If a connection remains unresponsive for a while, make sure policy is only notified once about
8154// it.
8155TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008157 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008158 WINDOW_LOCATION));
8159
8160 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008161 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008162 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008163 // 'notifyConnectionUnresponsive' should only be called once per connection
8164 mFakePolicy->assertNotifyAnrWasNotCalled();
8165 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008166 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008167 mWindow->consumeMotionEvent(
8168 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008169 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008170 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008171 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008172 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008173}
8174
8175/**
8176 * 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 -07008177 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008178 *
8179 * Warning!!!
8180 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8181 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008182 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008183 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8184 *
8185 * If that value changes, this test should also change.
8186 */
8187TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8188 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008189 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008190
8191 tapOnWindow();
8192 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8193 ASSERT_TRUE(downSequenceNum);
8194 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8195 ASSERT_TRUE(upSequenceNum);
8196 // Don't finish the events yet, and send a key
8197 // Injection will "succeed" because we will eventually give up and send the key to the focused
8198 // window even if motions are still being processed. But because the injection timeout is short,
8199 // we will receive INJECTION_TIMED_OUT as the result.
8200
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008201 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008202 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8203 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008204 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008205 // Key will not be sent to the window, yet, because the window is still processing events
8206 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008207 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8208 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8209 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8210 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008211
8212 std::this_thread::sleep_for(500ms);
8213 // if we wait long enough though, dispatcher will give up, and still send the key
8214 // to the focused window, even though we have not yet finished the motion event
8215 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8216 mWindow->finishEvent(*downSequenceNum);
8217 mWindow->finishEvent(*upSequenceNum);
8218}
8219
8220/**
8221 * If a window is processing a motion event, and then a key event comes in, the key event should
8222 * not go to the focused window until the motion is processed.
8223 * If then a new motion comes in, then the pending key event should be going to the currently
8224 * focused window right away.
8225 */
8226TEST_F(InputDispatcherSingleWindowAnr,
8227 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8228 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008229 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008230
8231 tapOnWindow();
8232 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8233 ASSERT_TRUE(downSequenceNum);
8234 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8235 ASSERT_TRUE(upSequenceNum);
8236 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008237 mDispatcher->notifyKey(
8238 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8239 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8240 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008241 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008242 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8243 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8244 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8245 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008246
8247 // Now tap down again. It should cause the pending key to go to the focused window right away.
8248 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008249 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8250 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008251 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8252 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008253 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8254 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008255 mWindow->assertNoEvents();
8256}
8257
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008258/**
8259 * Send an event to the app and have the app not respond right away.
8260 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8261 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8262 * At some point, the window becomes responsive again.
8263 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8264 */
8265TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8266 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8267 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8268 .build());
8269
8270 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8271 ASSERT_TRUE(sequenceNum);
8272 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8273 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8274
8275 mWindow->finishEvent(*sequenceNum);
8276 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8277 ASSERT_TRUE(mDispatcher->waitForIdle());
8278 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8279
8280 // Now that the window is responsive, let's continue the gesture.
8281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8282 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8283 .build());
8284
8285 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8286 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8287 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8288 .build());
8289
8290 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8291 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8292 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8293 .build());
8294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8295 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8296 .build());
8297 // We already canceled this pointer, so the window shouldn't get any new events.
8298 mWindow->assertNoEvents();
8299
8300 // Start another one.
8301 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8302 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8303 .build());
8304 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8305}
8306
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008307class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8308 virtual void SetUp() override {
8309 InputDispatcherTest::SetUp();
8310
Chris Yea209fde2020-07-22 13:54:51 -07008311 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008312 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008313 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8314 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008315 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008316 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008317 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008318
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008319 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8320 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008321 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008322 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008323
8324 // Set focused application.
8325 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008326 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008327
8328 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008329 mDispatcher->onWindowInfosChanged(
8330 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008331 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008332 mFocusedWindow->consumeFocusEvent(true);
8333 }
8334
8335 virtual void TearDown() override {
8336 InputDispatcherTest::TearDown();
8337
8338 mUnfocusedWindow.clear();
8339 mFocusedWindow.clear();
8340 }
8341
8342protected:
Chris Yea209fde2020-07-22 13:54:51 -07008343 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008344 sp<FakeWindowHandle> mUnfocusedWindow;
8345 sp<FakeWindowHandle> mFocusedWindow;
8346 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8347 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8348 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8349
8350 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8351
8352 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8353
8354private:
8355 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008357 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008358 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008360 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008361 location));
8362 }
8363};
8364
8365// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8366// should be ANR'd first.
8367TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008369 injectMotionEvent(*mDispatcher,
8370 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8371 AINPUT_SOURCE_TOUCHSCREEN)
8372 .pointer(PointerBuilder(0, ToolType::FINGER)
8373 .x(FOCUSED_WINDOW_LOCATION.x)
8374 .y(FOCUSED_WINDOW_LOCATION.y))
8375 .build()));
8376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8377 injectMotionEvent(*mDispatcher,
8378 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8379 AINPUT_SOURCE_TOUCHSCREEN)
8380 .pointer(PointerBuilder(0, ToolType::FINGER)
8381 .x(FOCUSED_WINDOW_LOCATION.x)
8382 .y(FOCUSED_WINDOW_LOCATION.y))
8383 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008384 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008385 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008386 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008387 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008388 // We consumed all events, so no ANR
8389 ASSERT_TRUE(mDispatcher->waitForIdle());
8390 mFakePolicy->assertNotifyAnrWasNotCalled();
8391
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008393 injectMotionEvent(*mDispatcher,
8394 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8395 AINPUT_SOURCE_TOUCHSCREEN)
8396 .pointer(PointerBuilder(0, ToolType::FINGER)
8397 .x(FOCUSED_WINDOW_LOCATION.x)
8398 .y(FOCUSED_WINDOW_LOCATION.y))
8399 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008400 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8401 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008402
8403 const std::chrono::duration timeout =
8404 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008405 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008406
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008407 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008408 mFocusedWindow->consumeMotionDown();
8409 // This cancel is generated because the connection was unresponsive
8410 mFocusedWindow->consumeMotionCancel();
8411 mFocusedWindow->assertNoEvents();
8412 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008413 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008414 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8415 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008416 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008417}
8418
8419// If we have 2 windows with identical timeouts that are both unresponsive,
8420// it doesn't matter which order they should have ANR.
8421// But we should receive ANR for both.
8422TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8423 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008424 mUnfocusedWindow->setDispatchingTimeout(
8425 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008426 mDispatcher->onWindowInfosChanged(
8427 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008428
8429 tapOnFocusedWindow();
8430 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008431 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008432 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8433 mFocusedWindow->getDispatchingTimeout(
8434 DISPATCHING_TIMEOUT)),
8435 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8436
8437 ASSERT_THAT(anrConnectionTokens,
8438 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8439 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008440
8441 ASSERT_TRUE(mDispatcher->waitForIdle());
8442 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008443
8444 mFocusedWindow->consumeMotionDown();
8445 mFocusedWindow->consumeMotionUp();
8446 mUnfocusedWindow->consumeMotionOutside();
8447
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008448 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8449 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008450
8451 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008452 ASSERT_THAT(responsiveTokens,
8453 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8454 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008455 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008456}
8457
8458// If a window is already not responding, the second tap on the same window should be ignored.
8459// We should also log an error to account for the dropped event (not tested here).
8460// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8461TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8462 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008463 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008464 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008465 // Receive the events, but don't respond
8466 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8467 ASSERT_TRUE(downEventSequenceNum);
8468 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8469 ASSERT_TRUE(upEventSequenceNum);
8470 const std::chrono::duration timeout =
8471 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008472 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008473
8474 // Tap once again
8475 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008476 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008477 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008478 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008479 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008480 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008481 FOCUSED_WINDOW_LOCATION));
8482 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8483 // valid touch target
8484 mUnfocusedWindow->assertNoEvents();
8485
8486 // Consume the first tap
8487 mFocusedWindow->finishEvent(*downEventSequenceNum);
8488 mFocusedWindow->finishEvent(*upEventSequenceNum);
8489 ASSERT_TRUE(mDispatcher->waitForIdle());
8490 // The second tap did not go to the focused window
8491 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008492 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008493 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8494 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008495 mFakePolicy->assertNotifyAnrWasNotCalled();
8496}
8497
8498// If you tap outside of all windows, there will not be ANR
8499TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008500 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008501 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008502 LOCATION_OUTSIDE_ALL_WINDOWS));
8503 ASSERT_TRUE(mDispatcher->waitForIdle());
8504 mFakePolicy->assertNotifyAnrWasNotCalled();
8505}
8506
8507// Since the focused window is paused, tapping on it should not produce any events
8508TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8509 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008510 mDispatcher->onWindowInfosChanged(
8511 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008513 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008515 FOCUSED_WINDOW_LOCATION));
8516
8517 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8518 ASSERT_TRUE(mDispatcher->waitForIdle());
8519 // Should not ANR because the window is paused, and touches shouldn't go to it
8520 mFakePolicy->assertNotifyAnrWasNotCalled();
8521
8522 mFocusedWindow->assertNoEvents();
8523 mUnfocusedWindow->assertNoEvents();
8524}
8525
8526/**
8527 * 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 -07008528 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008529 * If a different window becomes focused at this time, the key should go to that window instead.
8530 *
8531 * Warning!!!
8532 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8533 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008534 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008535 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8536 *
8537 * If that value changes, this test should also change.
8538 */
8539TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8540 // Set a long ANR timeout to prevent it from triggering
8541 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008542 mDispatcher->onWindowInfosChanged(
8543 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008544
8545 tapOnUnfocusedWindow();
8546 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8547 ASSERT_TRUE(downSequenceNum);
8548 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8549 ASSERT_TRUE(upSequenceNum);
8550 // Don't finish the events yet, and send a key
8551 // Injection will succeed because we will eventually give up and send the key to the focused
8552 // window even if motions are still being processed.
8553
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008554 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008555 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8556 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008558 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008559 // and the key remains pending, waiting for the touch events to be processed.
8560 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8561 // under the hood.
8562 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8563 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008564
8565 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008566 mFocusedWindow->setFocusable(false);
8567 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008568 mDispatcher->onWindowInfosChanged(
8569 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008570 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008571
8572 // Focus events should precede the key events
8573 mUnfocusedWindow->consumeFocusEvent(true);
8574 mFocusedWindow->consumeFocusEvent(false);
8575
8576 // Finish the tap events, which should unblock dispatcher
8577 mUnfocusedWindow->finishEvent(*downSequenceNum);
8578 mUnfocusedWindow->finishEvent(*upSequenceNum);
8579
8580 // Now that all queues are cleared and no backlog in the connections, the key event
8581 // can finally go to the newly focused "mUnfocusedWindow".
8582 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8583 mFocusedWindow->assertNoEvents();
8584 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008585 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008586}
8587
8588// When the touch stream is split across 2 windows, and one of them does not respond,
8589// then ANR should be raised and the touch should be canceled for the unresponsive window.
8590// The other window should not be affected by that.
8591TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8592 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8594 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8595 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008596 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008597 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008598
8599 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008600 mDispatcher->notifyMotion(
8601 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8602 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008603
8604 const std::chrono::duration timeout =
8605 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008606 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008607
8608 mUnfocusedWindow->consumeMotionDown();
8609 mFocusedWindow->consumeMotionDown();
8610 // Focused window may or may not receive ACTION_MOVE
8611 // But it should definitely receive ACTION_CANCEL due to the ANR
8612 InputEvent* event;
8613 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8614 ASSERT_TRUE(moveOrCancelSequenceNum);
8615 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8616 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008617 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008618 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8619 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8620 mFocusedWindow->consumeMotionCancel();
8621 } else {
8622 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8623 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008624 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008625 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8626 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008627
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008628 mUnfocusedWindow->assertNoEvents();
8629 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008630 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008631}
8632
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008633/**
8634 * If we have no focused window, and a key comes in, we start the ANR timer.
8635 * The focused application should add a focused window before the timer runs out to prevent ANR.
8636 *
8637 * If the user touches another application during this time, the key should be dropped.
8638 * Next, if a new focused window comes in, without toggling the focused application,
8639 * then no ANR should occur.
8640 *
8641 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8642 * but in some cases the policy may not update the focused application.
8643 */
8644TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8645 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8646 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008647 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008648 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8649 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8650 mFocusedWindow->setFocusable(false);
8651
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008652 mDispatcher->onWindowInfosChanged(
8653 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008654 mFocusedWindow->consumeFocusEvent(false);
8655
8656 // Send a key. The ANR timer should start because there is no focused window.
8657 // 'focusedApplication' will get blamed if this timer completes.
8658 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008659 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008660 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8661 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008662 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008664
8665 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8666 // then the injected touches won't cause the focused event to get dropped.
8667 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8668 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8669 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8670 // For this test, it means that the key would get delivered to the window once it becomes
8671 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008672 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008673
8674 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008675 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8676 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8677 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008678
8679 // We do not consume the motion right away, because that would require dispatcher to first
8680 // process (== drop) the key event, and by that time, ANR will be raised.
8681 // Set the focused window first.
8682 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008683 mDispatcher->onWindowInfosChanged(
8684 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008685 setFocusedWindow(mFocusedWindow);
8686 mFocusedWindow->consumeFocusEvent(true);
8687 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8688 // to another application. This could be a bug / behaviour in the policy.
8689
8690 mUnfocusedWindow->consumeMotionDown();
8691
8692 ASSERT_TRUE(mDispatcher->waitForIdle());
8693 // Should not ANR because we actually have a focused window. It was just added too slowly.
8694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8695}
8696
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008697// These tests ensure we cannot send touch events to a window that's positioned behind a window
8698// that has feature NO_INPUT_CHANNEL.
8699// Layout:
8700// Top (closest to user)
8701// mNoInputWindow (above all windows)
8702// mBottomWindow
8703// Bottom (furthest from user)
8704class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8705 virtual void SetUp() override {
8706 InputDispatcherTest::SetUp();
8707
8708 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008709 mNoInputWindow =
8710 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8711 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008712 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008713 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008714 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8715 // It's perfectly valid for this window to not have an associated input channel
8716
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008717 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8718 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008719 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8720
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008721 mDispatcher->onWindowInfosChanged(
8722 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008723 }
8724
8725protected:
8726 std::shared_ptr<FakeApplicationHandle> mApplication;
8727 sp<FakeWindowHandle> mNoInputWindow;
8728 sp<FakeWindowHandle> mBottomWindow;
8729};
8730
8731TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8732 PointF touchedPoint = {10, 10};
8733
Prabir Pradhan678438e2023-04-13 19:32:51 +00008734 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8735 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8736 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008737
8738 mNoInputWindow->assertNoEvents();
8739 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8740 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8741 // and therefore should prevent mBottomWindow from receiving touches
8742 mBottomWindow->assertNoEvents();
8743}
8744
8745/**
8746 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8747 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8748 */
8749TEST_F(InputDispatcherMultiWindowOcclusionTests,
8750 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008751 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8752 "Window with input channel and NO_INPUT_CHANNEL",
8753 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008754
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008755 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008756 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008757 mDispatcher->onWindowInfosChanged(
8758 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008759
8760 PointF touchedPoint = {10, 10};
8761
Prabir Pradhan678438e2023-04-13 19:32:51 +00008762 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8763 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8764 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008765
8766 mNoInputWindow->assertNoEvents();
8767 mBottomWindow->assertNoEvents();
8768}
8769
Vishnu Nair958da932020-08-21 17:12:37 -07008770class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8771protected:
8772 std::shared_ptr<FakeApplicationHandle> mApp;
8773 sp<FakeWindowHandle> mWindow;
8774 sp<FakeWindowHandle> mMirror;
8775
8776 virtual void SetUp() override {
8777 InputDispatcherTest::SetUp();
8778 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008779 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8780 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8781 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008782 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8783 mWindow->setFocusable(true);
8784 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008785 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008786 }
8787};
8788
8789TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8790 // Request focus on a mirrored window
8791 setFocusedWindow(mMirror);
8792
8793 // window gets focused
8794 mWindow->consumeFocusEvent(true);
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);
8798}
8799
8800// A focused & mirrored window remains focused only if the window and its mirror are both
8801// focusable.
8802TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8803 setFocusedWindow(mMirror);
8804
8805 // window gets focused
8806 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008808 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008809 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008811 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008812 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8813
8814 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008815 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008816
8817 // window loses focus since one of the windows associated with the token in not focusable
8818 mWindow->consumeFocusEvent(false);
8819
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008820 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008821 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008822 mWindow->assertNoEvents();
8823}
8824
8825// A focused & mirrored window remains focused until the window and its mirror both become
8826// invisible.
8827TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8828 setFocusedWindow(mMirror);
8829
8830 // window gets focused
8831 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008833 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008834 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008836 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008837 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8838
8839 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008840 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008841
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008843 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008844 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008846 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008847 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8848
8849 mWindow->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
8852 // window loses focus only after all windows associated with the token become invisible.
8853 mWindow->consumeFocusEvent(false);
8854
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008855 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008856 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008857 mWindow->assertNoEvents();
8858}
8859
8860// A focused & mirrored window remains focused until both windows are removed.
8861TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8862 setFocusedWindow(mMirror);
8863
8864 // window gets focused
8865 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008867 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008868 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008870 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008871 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8872
8873 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008874 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008875
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008877 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008878 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008880 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008881 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8882
8883 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008884 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008885 mWindow->consumeFocusEvent(false);
8886
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008887 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008888 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008889 mWindow->assertNoEvents();
8890}
8891
8892// Focus request can be pending until one window becomes visible.
8893TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8894 // Request focus on an invisible mirror.
8895 mWindow->setVisible(false);
8896 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008897 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008898 setFocusedWindow(mMirror);
8899
8900 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008902 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8903 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008904
8905 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008906 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008907
8908 // window gets focused
8909 mWindow->consumeFocusEvent(true);
8910 // window gets the pending key event
8911 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8912}
Prabir Pradhan99987712020-11-10 18:43:05 -08008913
8914class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8915protected:
8916 std::shared_ptr<FakeApplicationHandle> mApp;
8917 sp<FakeWindowHandle> mWindow;
8918 sp<FakeWindowHandle> mSecondWindow;
8919
8920 void SetUp() override {
8921 InputDispatcherTest::SetUp();
8922 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008923 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008924 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008925 mSecondWindow =
8926 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008927 mSecondWindow->setFocusable(true);
8928
8929 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008930 mDispatcher->onWindowInfosChanged(
8931 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008932
8933 setFocusedWindow(mWindow);
8934 mWindow->consumeFocusEvent(true);
8935 }
8936
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008937 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008938 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008939 }
8940
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008941 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8942 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008943 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008944 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8945 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008946 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008947 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008948 }
8949};
8950
8951TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8952 // Ensure that capture cannot be obtained for unfocused windows.
8953 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8954 mFakePolicy->assertSetPointerCaptureNotCalled();
8955 mSecondWindow->assertNoEvents();
8956
8957 // Ensure that capture can be enabled from the focus window.
8958 requestAndVerifyPointerCapture(mWindow, true);
8959
8960 // Ensure that capture cannot be disabled from a window that does not have capture.
8961 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8962 mFakePolicy->assertSetPointerCaptureNotCalled();
8963
8964 // Ensure that capture can be disabled from the window with capture.
8965 requestAndVerifyPointerCapture(mWindow, false);
8966}
8967
8968TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008969 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008970
8971 setFocusedWindow(mSecondWindow);
8972
8973 // Ensure that the capture disabled event was sent first.
8974 mWindow->consumeCaptureEvent(false);
8975 mWindow->consumeFocusEvent(false);
8976 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008977 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008978
8979 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008980 notifyPointerCaptureChanged({});
8981 notifyPointerCaptureChanged(request);
8982 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008983 mWindow->assertNoEvents();
8984 mSecondWindow->assertNoEvents();
8985 mFakePolicy->assertSetPointerCaptureNotCalled();
8986}
8987
8988TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008989 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008990
8991 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008992 notifyPointerCaptureChanged({});
8993 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008994
8995 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008996 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008997 mWindow->consumeCaptureEvent(false);
8998 mWindow->assertNoEvents();
8999}
9000
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009001TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9002 requestAndVerifyPointerCapture(mWindow, true);
9003
9004 // The first window loses focus.
9005 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009006 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009007 mWindow->consumeCaptureEvent(false);
9008
9009 // Request Pointer Capture from the second window before the notification from InputReader
9010 // arrives.
9011 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009012 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009013
9014 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009015 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009016
9017 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009018 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009019
9020 mSecondWindow->consumeFocusEvent(true);
9021 mSecondWindow->consumeCaptureEvent(true);
9022}
9023
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009024TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9025 // App repeatedly enables and disables capture.
9026 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9027 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9028 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9029 mFakePolicy->assertSetPointerCaptureCalled(false);
9030 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9031 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9032
9033 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9034 // first request is now stale, this should do nothing.
9035 notifyPointerCaptureChanged(firstRequest);
9036 mWindow->assertNoEvents();
9037
9038 // InputReader notifies that the second request was enabled.
9039 notifyPointerCaptureChanged(secondRequest);
9040 mWindow->consumeCaptureEvent(true);
9041}
9042
Prabir Pradhan7092e262022-05-03 16:51:09 +00009043TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9044 requestAndVerifyPointerCapture(mWindow, true);
9045
9046 // App toggles pointer capture off and on.
9047 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9048 mFakePolicy->assertSetPointerCaptureCalled(false);
9049
9050 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9051 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9052
9053 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9054 // preceding "disable" request.
9055 notifyPointerCaptureChanged(enableRequest);
9056
9057 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9058 // any notifications.
9059 mWindow->assertNoEvents();
9060}
9061
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009062/**
9063 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9064 * mouse movements don't affect the previous mouse hovering state.
9065 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9066 * HOVER_MOVE events).
9067 */
9068TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9069 // Mouse hover on the window
9070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9071 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9072 .build());
9073 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9074 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9075 .build());
9076
9077 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9078 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9079
9080 // Start pointer capture
9081 requestAndVerifyPointerCapture(mWindow, true);
9082
9083 // Send some relative mouse movements and receive them in the window.
9084 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9085 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9086 .build());
9087 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9088 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9089
9090 // Stop pointer capture
9091 requestAndVerifyPointerCapture(mWindow, false);
9092
9093 // Continue hovering on the window
9094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9095 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9096 .build());
9097 mWindow->consumeMotionEvent(
9098 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9099
9100 mWindow->assertNoEvents();
9101}
9102
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009103class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9104protected:
9105 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009106
9107 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9108 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9109
9110 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9111 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9112
9113 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9114 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9115 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9116 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9117 MAXIMUM_OBSCURING_OPACITY);
9118
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009119 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9120 static constexpr gui::Uid APP_B_UID{10002};
9121 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009122
9123 sp<FakeWindowHandle> mTouchWindow;
9124
9125 virtual void SetUp() override {
9126 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009127 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009128 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9129 }
9130
9131 virtual void TearDown() override {
9132 InputDispatcherTest::TearDown();
9133 mTouchWindow.clear();
9134 }
9135
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009136 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009137 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009138 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009139 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009140 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009141 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009142 return window;
9143 }
9144
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009145 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009146 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9147 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009148 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009149 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009150 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009151 return window;
9152 }
9153
9154 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9156 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9157 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009158 }
9159};
9160
9161TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009162 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009163 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009164 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009165
9166 touch();
9167
9168 mTouchWindow->assertNoEvents();
9169}
9170
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009171TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009172 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9173 const sp<FakeWindowHandle>& w =
9174 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009175 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009176
9177 touch();
9178
9179 mTouchWindow->assertNoEvents();
9180}
9181
9182TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009183 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9184 const sp<FakeWindowHandle>& w =
9185 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009186 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009187
9188 touch();
9189
9190 w->assertNoEvents();
9191}
9192
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009193TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009194 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009195 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009196
9197 touch();
9198
9199 mTouchWindow->consumeAnyMotionDown();
9200}
9201
9202TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009203 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009204 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009205 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009206 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009207
9208 touch({PointF{100, 100}});
9209
9210 mTouchWindow->consumeAnyMotionDown();
9211}
9212
9213TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009214 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009215 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009216 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009217
9218 touch();
9219
9220 mTouchWindow->consumeAnyMotionDown();
9221}
9222
9223TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9224 const sp<FakeWindowHandle>& w =
9225 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009226 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009227
9228 touch();
9229
9230 mTouchWindow->consumeAnyMotionDown();
9231}
9232
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009233TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9234 const sp<FakeWindowHandle>& w =
9235 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009236 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009237
9238 touch();
9239
9240 w->assertNoEvents();
9241}
9242
9243/**
9244 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9245 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9246 * window, the occluding window will still receive ACTION_OUTSIDE event.
9247 */
9248TEST_F(InputDispatcherUntrustedTouchesTest,
9249 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9250 const sp<FakeWindowHandle>& w =
9251 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009252 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009253 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009254
9255 touch();
9256
9257 w->consumeMotionOutside();
9258}
9259
9260TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9261 const sp<FakeWindowHandle>& w =
9262 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009263 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009264 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009265
9266 touch();
9267
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009268 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009269}
9270
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009271TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009272 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009273 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9274 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009275 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009276
9277 touch();
9278
9279 mTouchWindow->consumeAnyMotionDown();
9280}
9281
9282TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9283 const sp<FakeWindowHandle>& w =
9284 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9285 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009286 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009287
9288 touch();
9289
9290 mTouchWindow->consumeAnyMotionDown();
9291}
9292
9293TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009294 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009295 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9296 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009297 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009298
9299 touch();
9300
9301 mTouchWindow->assertNoEvents();
9302}
9303
9304TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9305 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9306 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009307 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9308 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009309 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009310 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9311 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009312 mDispatcher->onWindowInfosChanged(
9313 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009314
9315 touch();
9316
9317 mTouchWindow->assertNoEvents();
9318}
9319
9320TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9321 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9322 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009323 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9324 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009325 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009326 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9327 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009328 mDispatcher->onWindowInfosChanged(
9329 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009330
9331 touch();
9332
9333 mTouchWindow->consumeAnyMotionDown();
9334}
9335
9336TEST_F(InputDispatcherUntrustedTouchesTest,
9337 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9338 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009339 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9340 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009341 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009342 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9343 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009344 mDispatcher->onWindowInfosChanged(
9345 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009346
9347 touch();
9348
9349 mTouchWindow->consumeAnyMotionDown();
9350}
9351
9352TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9353 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9355 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009356 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009357 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9358 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009359 mDispatcher->onWindowInfosChanged(
9360 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009361
9362 touch();
9363
9364 mTouchWindow->assertNoEvents();
9365}
9366
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009367TEST_F(InputDispatcherUntrustedTouchesTest,
9368 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9369 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009370 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9371 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009372 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009373 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9374 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009375 mDispatcher->onWindowInfosChanged(
9376 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009377
9378 touch();
9379
9380 mTouchWindow->assertNoEvents();
9381}
9382
9383TEST_F(InputDispatcherUntrustedTouchesTest,
9384 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9385 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009386 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9387 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009388 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009389 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9390 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009391 mDispatcher->onWindowInfosChanged(
9392 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009393
9394 touch();
9395
9396 mTouchWindow->consumeAnyMotionDown();
9397}
9398
9399TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9400 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009401 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9402 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009403 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009404
9405 touch();
9406
9407 mTouchWindow->consumeAnyMotionDown();
9408}
9409
9410TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9411 const sp<FakeWindowHandle>& w =
9412 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009413 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009414
9415 touch();
9416
9417 mTouchWindow->consumeAnyMotionDown();
9418}
9419
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009420TEST_F(InputDispatcherUntrustedTouchesTest,
9421 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9422 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9423 const sp<FakeWindowHandle>& w =
9424 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009425 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009426
9427 touch();
9428
9429 mTouchWindow->assertNoEvents();
9430}
9431
9432TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9433 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9434 const sp<FakeWindowHandle>& w =
9435 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009436 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009437
9438 touch();
9439
9440 mTouchWindow->consumeAnyMotionDown();
9441}
9442
9443TEST_F(InputDispatcherUntrustedTouchesTest,
9444 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9445 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9446 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009447 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9448 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009449 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009450
9451 touch();
9452
9453 mTouchWindow->consumeAnyMotionDown();
9454}
9455
9456TEST_F(InputDispatcherUntrustedTouchesTest,
9457 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9458 const sp<FakeWindowHandle>& w1 =
9459 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9460 OPACITY_BELOW_THRESHOLD);
9461 const sp<FakeWindowHandle>& w2 =
9462 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9463 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009464 mDispatcher->onWindowInfosChanged(
9465 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009466
9467 touch();
9468
9469 mTouchWindow->assertNoEvents();
9470}
9471
9472/**
9473 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9474 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9475 * (which alone would result in allowing touches) does not affect the blocking behavior.
9476 */
9477TEST_F(InputDispatcherUntrustedTouchesTest,
9478 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9479 const sp<FakeWindowHandle>& wB =
9480 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9481 OPACITY_BELOW_THRESHOLD);
9482 const sp<FakeWindowHandle>& wC =
9483 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9484 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009485 mDispatcher->onWindowInfosChanged(
9486 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009487
9488 touch();
9489
9490 mTouchWindow->assertNoEvents();
9491}
9492
9493/**
9494 * This test is testing that a window from a different UID but with same application token doesn't
9495 * block the touch. Apps can share the application token for close UI collaboration for example.
9496 */
9497TEST_F(InputDispatcherUntrustedTouchesTest,
9498 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9499 const sp<FakeWindowHandle>& w =
9500 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9501 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009502 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009503
9504 touch();
9505
9506 mTouchWindow->consumeAnyMotionDown();
9507}
9508
arthurhungb89ccb02020-12-30 16:19:01 +08009509class InputDispatcherDragTests : public InputDispatcherTest {
9510protected:
9511 std::shared_ptr<FakeApplicationHandle> mApp;
9512 sp<FakeWindowHandle> mWindow;
9513 sp<FakeWindowHandle> mSecondWindow;
9514 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009515 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009516 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9517 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009518
9519 void SetUp() override {
9520 InputDispatcherTest::SetUp();
9521 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009522 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009523 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009524
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009525 mSecondWindow =
9526 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009527 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009528
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009529 mSpyWindow =
9530 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009531 mSpyWindow->setSpy(true);
9532 mSpyWindow->setTrustedOverlay(true);
9533 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9534
arthurhungb89ccb02020-12-30 16:19:01 +08009535 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009536 mDispatcher->onWindowInfosChanged(
9537 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9538 {},
9539 0,
9540 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009541 }
9542
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009543 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9544 switch (fromSource) {
9545 case AINPUT_SOURCE_TOUCHSCREEN:
9546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009547 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009548 ADISPLAY_ID_DEFAULT, {50, 50}))
9549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9550 break;
9551 case AINPUT_SOURCE_STYLUS:
9552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009553 injectMotionEvent(*mDispatcher,
9554 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9555 AINPUT_SOURCE_STYLUS)
9556 .buttonState(
9557 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9558 .pointer(PointerBuilder(0, ToolType::STYLUS)
9559 .x(50)
9560 .y(50))
9561 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009562 break;
9563 case AINPUT_SOURCE_MOUSE:
9564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009565 injectMotionEvent(*mDispatcher,
9566 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9567 AINPUT_SOURCE_MOUSE)
9568 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9569 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9570 ToolType::MOUSE)
9571 .x(50)
9572 .y(50))
9573 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009574 break;
9575 default:
9576 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9577 }
arthurhungb89ccb02020-12-30 16:19:01 +08009578
9579 // Window should receive motion event.
9580 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009581 // Spy window should also receive motion event
9582 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009583 }
9584
9585 // Start performing drag, we will create a drag window and transfer touch to it.
9586 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9587 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009588 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009589 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009590 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009591 }
arthurhungb89ccb02020-12-30 16:19:01 +08009592
9593 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009594 mDragWindow =
9595 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009596 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009597 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9598 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9599 {},
9600 0,
9601 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009602
9603 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009604 bool transferred =
9605 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009606 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009607 if (transferred) {
9608 mWindow->consumeMotionCancel();
9609 mDragWindow->consumeMotionDown();
9610 }
9611 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009612 }
9613};
9614
9615TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009616 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009617
9618 // Move on window.
9619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009620 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009621 ADISPLAY_ID_DEFAULT, {50, 50}))
9622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9623 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9624 mWindow->consumeDragEvent(false, 50, 50);
9625 mSecondWindow->assertNoEvents();
9626
9627 // Move to another window.
9628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009629 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009630 ADISPLAY_ID_DEFAULT, {150, 50}))
9631 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9632 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9633 mWindow->consumeDragEvent(true, 150, 50);
9634 mSecondWindow->consumeDragEvent(false, 50, 50);
9635
9636 // Move back to original window.
9637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009638 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009639 ADISPLAY_ID_DEFAULT, {50, 50}))
9640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9641 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9642 mWindow->consumeDragEvent(false, 50, 50);
9643 mSecondWindow->consumeDragEvent(true, -50, 50);
9644
9645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009646 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9647 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9649 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9650 mWindow->assertNoEvents();
9651 mSecondWindow->assertNoEvents();
9652}
9653
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009654TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009655 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009656
9657 // No cancel event after drag start
9658 mSpyWindow->assertNoEvents();
9659
9660 const MotionEvent secondFingerDownEvent =
9661 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9662 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009663 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9664 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009665 .build();
9666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009667 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009668 InputEventInjectionSync::WAIT_FOR_RESULT))
9669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9670
9671 // Receives cancel for first pointer after next pointer down
9672 mSpyWindow->consumeMotionCancel();
9673 mSpyWindow->consumeMotionDown();
9674
9675 mSpyWindow->assertNoEvents();
9676}
9677
arthurhungf452d0b2021-01-06 00:19:52 +08009678TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009679 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009680
9681 // Move on window.
9682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009683 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009684 ADISPLAY_ID_DEFAULT, {50, 50}))
9685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9686 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9687 mWindow->consumeDragEvent(false, 50, 50);
9688 mSecondWindow->assertNoEvents();
9689
9690 // Move to another window.
9691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009692 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009693 ADISPLAY_ID_DEFAULT, {150, 50}))
9694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9695 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9696 mWindow->consumeDragEvent(true, 150, 50);
9697 mSecondWindow->consumeDragEvent(false, 50, 50);
9698
9699 // drop to another window.
9700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009701 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009702 {150, 50}))
9703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9704 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009705 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009706 mWindow->assertNoEvents();
9707 mSecondWindow->assertNoEvents();
9708}
9709
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009710TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9711 startDrag();
9712
9713 // No cancel event after drag start
9714 mSpyWindow->assertNoEvents();
9715
9716 const MotionEvent secondFingerDownEvent =
9717 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9718 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9719 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9720 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9721 .build();
9722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9723 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9724 InputEventInjectionSync::WAIT_FOR_RESULT))
9725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9726
9727 // Receives cancel for first pointer after next pointer down
9728 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9729 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9730 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9731
9732 mSpyWindow->assertNoEvents();
9733
9734 // Spy window calls pilfer pointers
9735 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9736 mDragWindow->assertNoEvents();
9737
9738 const MotionEvent firstFingerMoveEvent =
9739 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9740 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9741 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9742 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9743 .build();
9744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9745 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9746 InputEventInjectionSync::WAIT_FOR_RESULT))
9747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9748
9749 // Drag window should still receive the new event
9750 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9751 mDragWindow->assertNoEvents();
9752}
9753
arthurhung6d4bed92021-03-17 11:59:33 +08009754TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009755 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009756
9757 // Move on window and keep button pressed.
9758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009759 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009760 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9761 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009762 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009763 .build()))
9764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9765 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9766 mWindow->consumeDragEvent(false, 50, 50);
9767 mSecondWindow->assertNoEvents();
9768
9769 // Move to another window and release button, expect to drop item.
9770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009771 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009772 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9773 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009774 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009775 .build()))
9776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9777 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9778 mWindow->assertNoEvents();
9779 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009780 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009781
9782 // nothing to the window.
9783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009784 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009785 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9786 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009788 .build()))
9789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9790 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9791 mWindow->assertNoEvents();
9792 mSecondWindow->assertNoEvents();
9793}
9794
Arthur Hung54745652022-04-20 07:17:41 +00009795TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009796 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009797
9798 // Set second window invisible.
9799 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009800 mDispatcher->onWindowInfosChanged(
9801 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009802
9803 // Move on window.
9804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009805 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009806 ADISPLAY_ID_DEFAULT, {50, 50}))
9807 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9808 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9809 mWindow->consumeDragEvent(false, 50, 50);
9810 mSecondWindow->assertNoEvents();
9811
9812 // Move to another window.
9813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009814 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009815 ADISPLAY_ID_DEFAULT, {150, 50}))
9816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9817 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9818 mWindow->consumeDragEvent(true, 150, 50);
9819 mSecondWindow->assertNoEvents();
9820
9821 // drop to another window.
9822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009823 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009824 {150, 50}))
9825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9826 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009827 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009828 mWindow->assertNoEvents();
9829 mSecondWindow->assertNoEvents();
9830}
9831
Arthur Hung54745652022-04-20 07:17:41 +00009832TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009833 // Ensure window could track pointerIds if it didn't support split touch.
9834 mWindow->setPreventSplitting(true);
9835
Arthur Hung54745652022-04-20 07:17:41 +00009836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009838 {50, 50}))
9839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9840 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9841
9842 const MotionEvent secondFingerDownEvent =
9843 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9844 .displayId(ADISPLAY_ID_DEFAULT)
9845 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009846 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9847 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009848 .build();
9849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009850 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009851 InputEventInjectionSync::WAIT_FOR_RESULT))
9852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009853 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009854
9855 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009856 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009857}
9858
9859TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9860 // First down on second window.
9861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009862 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009863 {150, 50}))
9864 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9865
9866 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9867
9868 // Second down on first window.
9869 const MotionEvent secondFingerDownEvent =
9870 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9871 .displayId(ADISPLAY_ID_DEFAULT)
9872 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009873 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9874 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009875 .build();
9876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009877 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009878 InputEventInjectionSync::WAIT_FOR_RESULT))
9879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9880 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9881
9882 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009883 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009884
9885 // Move on window.
9886 const MotionEvent secondFingerMoveEvent =
9887 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9888 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009889 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9890 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009891 .build();
9892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009893 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009894 InputEventInjectionSync::WAIT_FOR_RESULT));
9895 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9896 mWindow->consumeDragEvent(false, 50, 50);
9897 mSecondWindow->consumeMotionMove();
9898
9899 // Release the drag pointer should perform drop.
9900 const MotionEvent secondFingerUpEvent =
9901 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9902 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009903 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9904 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009905 .build();
9906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009907 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009908 InputEventInjectionSync::WAIT_FOR_RESULT));
9909 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009910 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009911 mWindow->assertNoEvents();
9912 mSecondWindow->consumeMotionMove();
9913}
9914
Arthur Hung3915c1f2022-05-31 07:17:17 +00009915TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009916 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009917
9918 // Update window of second display.
9919 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009920 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009921 mDispatcher->onWindowInfosChanged(
9922 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9923 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9924 {},
9925 0,
9926 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009927
9928 // Let second display has a touch state.
9929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009930 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009931 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9932 AINPUT_SOURCE_TOUCHSCREEN)
9933 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009934 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009935 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009936 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009937 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009938 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009939 mDispatcher->onWindowInfosChanged(
9940 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9941 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9942 {},
9943 0,
9944 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009945
9946 // Move on window.
9947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009948 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009949 ADISPLAY_ID_DEFAULT, {50, 50}))
9950 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9951 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9952 mWindow->consumeDragEvent(false, 50, 50);
9953 mSecondWindow->assertNoEvents();
9954
9955 // Move to another window.
9956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009957 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009958 ADISPLAY_ID_DEFAULT, {150, 50}))
9959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9960 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9961 mWindow->consumeDragEvent(true, 150, 50);
9962 mSecondWindow->consumeDragEvent(false, 50, 50);
9963
9964 // drop to another window.
9965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009966 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009967 {150, 50}))
9968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9969 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009970 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009971 mWindow->assertNoEvents();
9972 mSecondWindow->assertNoEvents();
9973}
9974
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009975TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9976 startDrag(true, AINPUT_SOURCE_MOUSE);
9977 // Move on window.
9978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009979 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009980 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9981 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009982 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009983 .x(50)
9984 .y(50))
9985 .build()))
9986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9987 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9988 mWindow->consumeDragEvent(false, 50, 50);
9989 mSecondWindow->assertNoEvents();
9990
9991 // Move to another window.
9992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009993 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009994 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9995 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009996 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009997 .x(150)
9998 .y(50))
9999 .build()))
10000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10001 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10002 mWindow->consumeDragEvent(true, 150, 50);
10003 mSecondWindow->consumeDragEvent(false, 50, 50);
10004
10005 // drop to another window.
10006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010007 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010008 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10009 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010010 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010011 .x(150)
10012 .y(50))
10013 .build()))
10014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10015 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010016 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010017 mWindow->assertNoEvents();
10018 mSecondWindow->assertNoEvents();
10019}
10020
Linnan Li5af92f92023-07-14 14:36:22 +080010021/**
10022 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10023 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10024 */
10025TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10026 // Down on second window
10027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10028 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10029 {150, 50}))
10030 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10031
10032 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10033 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10034
10035 // Down on first window
10036 const MotionEvent secondFingerDownEvent =
10037 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10038 .displayId(ADISPLAY_ID_DEFAULT)
10039 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10040 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10041 .build();
10042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10043 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10044 InputEventInjectionSync::WAIT_FOR_RESULT))
10045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10046 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10047 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10048 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10049
10050 // Start drag on first window
10051 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10052
10053 // Trigger cancel
10054 mDispatcher->cancelCurrentTouch();
10055 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10056 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10057 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10058
10059 ASSERT_TRUE(mDispatcher->waitForIdle());
10060 // The D&D finished with nullptr
10061 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10062
10063 // Remove drag window
10064 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10065
10066 // Inject a simple gesture, ensure dispatcher not crashed
10067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10068 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10069 PointF{50, 50}))
10070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10071 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10072
10073 const MotionEvent moveEvent =
10074 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10075 .displayId(ADISPLAY_ID_DEFAULT)
10076 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10077 .build();
10078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10079 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10080 InputEventInjectionSync::WAIT_FOR_RESULT))
10081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10082 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10083
10084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10085 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10086 {50, 50}))
10087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10088 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10089}
10090
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010091TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10092 // Start hovering over the window.
10093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10094 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10095 ADISPLAY_ID_DEFAULT, {50, 50}));
10096
10097 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10098 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10099
10100 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10101 << "Drag and drop should not work with a hovering pointer";
10102}
10103
Vishnu Nair062a8672021-09-03 16:07:44 -070010104class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10105
10106TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10107 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010108 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10109 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010110 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010111 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10112 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010113 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010114 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010115 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010116
10117 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010118 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010119 window->assertNoEvents();
10120
Prabir Pradhan678438e2023-04-13 19:32:51 +000010121 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10122 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010123 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10124 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010125 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010126 window->assertNoEvents();
10127
10128 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010129 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010130 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010131
Prabir Pradhan678438e2023-04-13 19:32:51 +000010132 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010133 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10134
Prabir Pradhan678438e2023-04-13 19:32:51 +000010135 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10136 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010137 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10138 window->assertNoEvents();
10139}
10140
10141TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10142 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10143 std::make_shared<FakeApplicationHandle>();
10144 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010145 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10146 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010147 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010148 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010149 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010151 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10152 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010153 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010154 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10156 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010157 mDispatcher->onWindowInfosChanged(
10158 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010159 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010160 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010161
10162 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010163 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010164 window->assertNoEvents();
10165
Prabir Pradhan678438e2023-04-13 19:32:51 +000010166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10167 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010168 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10169 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010170 window->assertNoEvents();
10171
10172 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010173 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010174 mDispatcher->onWindowInfosChanged(
10175 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010176
Prabir Pradhan678438e2023-04-13 19:32:51 +000010177 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010178 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10179
Prabir Pradhan678438e2023-04-13 19:32:51 +000010180 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10181 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010182 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10183 window->assertNoEvents();
10184}
10185
10186TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10187 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10188 std::make_shared<FakeApplicationHandle>();
10189 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010190 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10191 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010192 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010193 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010194 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10197 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010198 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010199 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10201 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010202 mDispatcher->onWindowInfosChanged(
10203 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010204 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010205 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010206
10207 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010208 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010209 window->assertNoEvents();
10210
Prabir Pradhan678438e2023-04-13 19:32:51 +000010211 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10212 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010213 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10214 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010215 window->assertNoEvents();
10216
10217 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010218 mDispatcher->onWindowInfosChanged(
10219 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010220
Prabir Pradhan678438e2023-04-13 19:32:51 +000010221 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010222 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10223
Prabir Pradhan678438e2023-04-13 19:32:51 +000010224 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10225 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010226 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10227 window->assertNoEvents();
10228}
10229
Antonio Kantekf16f2832021-09-28 04:39:20 +000010230class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10231protected:
10232 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010233 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010234 sp<FakeWindowHandle> mWindow;
10235 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010236 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010237
10238 void SetUp() override {
10239 InputDispatcherTest::SetUp();
10240
10241 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010242 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010243 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010244 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010245 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010246 mSecondWindow =
10247 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010248 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010249 mThirdWindow =
10250 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10251 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10252 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010253
10254 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010255 mDispatcher->onWindowInfosChanged(
10256 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10257 {},
10258 0,
10259 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010260 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010261 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010262
Antonio Kantek15beb512022-06-13 22:35:41 +000010263 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010264 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010265 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010266 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10267 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010268 mThirdWindow->assertNoEvents();
10269 }
10270
10271 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10272 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010273 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010274 SECOND_DISPLAY_ID)) {
10275 mWindow->assertNoEvents();
10276 mSecondWindow->assertNoEvents();
10277 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010278 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010279 }
10280
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010281 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010282 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010283 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10284 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010285 mWindow->consumeTouchModeEvent(inTouchMode);
10286 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010287 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010288 }
10289};
10290
Antonio Kantek26defcf2022-02-08 01:12:27 +000010291TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010292 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010293 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10294 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010295 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010296}
10297
Antonio Kantek26defcf2022-02-08 01:12:27 +000010298TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10299 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010300 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010301 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010302 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010303 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010304 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010305 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010306 mWindow->assertNoEvents();
10307 mSecondWindow->assertNoEvents();
10308}
10309
10310TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10311 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010312 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010313 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010314 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010315 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010316 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010317}
10318
Antonio Kantekf16f2832021-09-28 04:39:20 +000010319TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010320 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010321 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10322 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010323 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010324 mWindow->assertNoEvents();
10325 mSecondWindow->assertNoEvents();
10326}
10327
Antonio Kantek15beb512022-06-13 22:35:41 +000010328TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10329 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10330 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10331 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010332 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010333 mWindow->assertNoEvents();
10334 mSecondWindow->assertNoEvents();
10335 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10336}
10337
Antonio Kantek48710e42022-03-24 14:19:30 -070010338TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10339 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10341 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010342 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10343 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10344
10345 // Then remove focus.
10346 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010347 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010348
10349 // Assert that caller can switch touch mode by owning one of the last interacted window.
10350 const WindowInfo& windowInfo = *mWindow->getInfo();
10351 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10352 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010353 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010354}
10355
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010356class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10357public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010358 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010359 std::shared_ptr<FakeApplicationHandle> application =
10360 std::make_shared<FakeApplicationHandle>();
10361 std::string name = "Fake Spy ";
10362 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010363 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10364 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010365 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010366 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010367 return spy;
10368 }
10369
10370 sp<FakeWindowHandle> createForeground() {
10371 std::shared_ptr<FakeApplicationHandle> application =
10372 std::make_shared<FakeApplicationHandle>();
10373 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010374 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10375 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010376 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010377 return window;
10378 }
10379
10380private:
10381 int mSpyCount{0};
10382};
10383
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010384using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010385/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010386 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10387 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010388TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010389 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010390 ScopedSilentDeath _silentDeath;
10391
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010392 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010393 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010394 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010395 ".* not a trusted overlay");
10396}
10397
10398/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010399 * Input injection into a display with a spy window but no foreground windows should succeed.
10400 */
10401TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010402 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010403 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010404
10405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010406 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10408 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10409}
10410
10411/**
10412 * Verify the order in which different input windows receive events. The touched foreground window
10413 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10414 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10415 * receive events before ones belows it.
10416 *
10417 * Here, we set up a scenario with four windows in the following Z order from the top:
10418 * spy1, spy2, window, spy3.
10419 * We then inject an event and verify that the foreground "window" receives it first, followed by
10420 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10421 * window.
10422 */
10423TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10424 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010425 auto spy1 = createSpy();
10426 auto spy2 = createSpy();
10427 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010428 mDispatcher->onWindowInfosChanged(
10429 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010430 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10431 const size_t numChannels = channels.size();
10432
Michael Wright8e9a8562022-02-09 13:44:29 +000010433 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010434 if (!epollFd.ok()) {
10435 FAIL() << "Failed to create epoll fd";
10436 }
10437
10438 for (size_t i = 0; i < numChannels; i++) {
10439 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10440 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10441 FAIL() << "Failed to add fd to epoll";
10442 }
10443 }
10444
10445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010446 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010447 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10448
10449 std::vector<size_t> eventOrder;
10450 std::vector<struct epoll_event> events(numChannels);
10451 for (;;) {
10452 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10453 (100ms).count());
10454 if (nFds < 0) {
10455 FAIL() << "Failed to call epoll_wait";
10456 }
10457 if (nFds == 0) {
10458 break; // epoll_wait timed out
10459 }
10460 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010461 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010462 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010463 channels[i]->consumeMotionDown();
10464 }
10465 }
10466
10467 // Verify the order in which the events were received.
10468 EXPECT_EQ(3u, eventOrder.size());
10469 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10470 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10471 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10472}
10473
10474/**
10475 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10476 */
10477TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10478 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010479 auto spy = createSpy();
10480 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010481 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010482
10483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010484 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010485 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10486 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10487 spy->assertNoEvents();
10488}
10489
10490/**
10491 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10492 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10493 * to the window.
10494 */
10495TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10496 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010497 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010498 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010499 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010500
10501 // Inject an event outside the spy window's touchable region.
10502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010503 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10505 window->consumeMotionDown();
10506 spy->assertNoEvents();
10507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010508 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010509 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10510 window->consumeMotionUp();
10511 spy->assertNoEvents();
10512
10513 // Inject an event inside the spy window's touchable region.
10514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010516 {5, 10}))
10517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10518 window->consumeMotionDown();
10519 spy->consumeMotionDown();
10520}
10521
10522/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010523 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010524 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010525 */
10526TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10527 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010528 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010529 auto spy = createSpy();
10530 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010531 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010532 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010533 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010534
10535 // Inject an event outside the spy window's frame and touchable region.
10536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010537 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010538 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010539 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10540 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010541 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010542}
10543
10544/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010545 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10546 * pointers that are down within its bounds.
10547 */
10548TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10549 auto windowLeft = createForeground();
10550 windowLeft->setFrame({0, 0, 100, 200});
10551 auto windowRight = createForeground();
10552 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010553 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010554 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010555 mDispatcher->onWindowInfosChanged(
10556 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010557
10558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010559 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010560 {50, 50}))
10561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10562 windowLeft->consumeMotionDown();
10563 spy->consumeMotionDown();
10564
10565 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010566 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010567 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010568 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10569 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010570 .build();
10571 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010572 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010573 InputEventInjectionSync::WAIT_FOR_RESULT))
10574 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10575 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010576 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010577}
10578
10579/**
10580 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10581 * the spy should receive the second pointer with ACTION_DOWN.
10582 */
10583TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10584 auto window = createForeground();
10585 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010586 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010587 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010588 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010589
10590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010591 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010592 {50, 50}))
10593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10594 window->consumeMotionDown();
10595 spyRight->assertNoEvents();
10596
10597 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010598 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010599 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010600 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10601 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010602 .build();
10603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010604 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010605 InputEventInjectionSync::WAIT_FOR_RESULT))
10606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010607 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010608 spyRight->consumeMotionDown();
10609}
10610
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010611/**
10612 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10613 * windows should be allowed to control split touch.
10614 */
10615TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010616 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010617 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010618 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010619 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010620
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010621 auto window = createForeground();
10622 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010623
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010624 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010625
10626 // First finger down, no window touched.
10627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010628 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010629 {100, 200}))
10630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10631 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10632 window->assertNoEvents();
10633
10634 // Second finger down on window, the window should receive touch down.
10635 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010636 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010637 .displayId(ADISPLAY_ID_DEFAULT)
10638 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010639 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10640 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010641 .build();
10642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010643 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010644 InputEventInjectionSync::WAIT_FOR_RESULT))
10645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10646
10647 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010648 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010649}
10650
10651/**
10652 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10653 * do not receive key events.
10654 */
10655TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010656 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010657 spy->setFocusable(false);
10658
10659 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010660 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010661 setFocusedWindow(window);
10662 window->consumeFocusEvent(true);
10663
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010665 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10666 window->consumeKeyDown(ADISPLAY_ID_NONE);
10667
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010669 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10670 window->consumeKeyUp(ADISPLAY_ID_NONE);
10671
10672 spy->assertNoEvents();
10673}
10674
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010675using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10676
10677/**
10678 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10679 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10680 */
10681TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10682 auto window = createForeground();
10683 auto spy1 = createSpy();
10684 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010685 mDispatcher->onWindowInfosChanged(
10686 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010687
10688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010689 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10691 window->consumeMotionDown();
10692 spy1->consumeMotionDown();
10693 spy2->consumeMotionDown();
10694
10695 // Pilfer pointers from the second spy window.
10696 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10697 spy2->assertNoEvents();
10698 spy1->consumeMotionCancel();
10699 window->consumeMotionCancel();
10700
10701 // The rest of the gesture should only be sent to the second spy window.
10702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010703 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010704 ADISPLAY_ID_DEFAULT))
10705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10706 spy2->consumeMotionMove();
10707 spy1->assertNoEvents();
10708 window->assertNoEvents();
10709}
10710
10711/**
10712 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10713 * in the middle of the gesture.
10714 */
10715TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10716 auto window = createForeground();
10717 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010718 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010719
10720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10723 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10724 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10725
10726 window->releaseChannel();
10727
10728 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10729
10730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010731 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10733 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10734}
10735
10736/**
10737 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10738 * the spy, but not to any other windows.
10739 */
10740TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10741 auto spy = createSpy();
10742 auto window = createForeground();
10743
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010744 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010745
10746 // First finger down on the window and the spy.
10747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010748 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010749 {100, 200}))
10750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10751 spy->consumeMotionDown();
10752 window->consumeMotionDown();
10753
10754 // Spy window pilfers the pointers.
10755 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10756 window->consumeMotionCancel();
10757
10758 // Second finger down on the window and spy, but the window should not receive the pointer down.
10759 const MotionEvent secondFingerDownEvent =
10760 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10761 .displayId(ADISPLAY_ID_DEFAULT)
10762 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010763 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10764 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010765 .build();
10766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010767 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010768 InputEventInjectionSync::WAIT_FOR_RESULT))
10769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10770
Harry Cutts33476232023-01-30 19:57:29 +000010771 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010772
10773 // Third finger goes down outside all windows, so injection should fail.
10774 const MotionEvent thirdFingerDownEvent =
10775 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10776 .displayId(ADISPLAY_ID_DEFAULT)
10777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10780 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010781 .build();
10782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010783 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010784 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010785 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010786
10787 spy->assertNoEvents();
10788 window->assertNoEvents();
10789}
10790
10791/**
10792 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10793 */
10794TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10795 auto spy = createSpy();
10796 spy->setFrame(Rect(0, 0, 100, 100));
10797 auto window = createForeground();
10798 window->setFrame(Rect(0, 0, 200, 200));
10799
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010800 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010801
10802 // First finger down on the window only
10803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010804 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010805 {150, 150}))
10806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10807 window->consumeMotionDown();
10808
10809 // Second finger down on the spy and window
10810 const MotionEvent secondFingerDownEvent =
10811 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10812 .displayId(ADISPLAY_ID_DEFAULT)
10813 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010814 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10815 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010816 .build();
10817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010818 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010819 InputEventInjectionSync::WAIT_FOR_RESULT))
10820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10821 spy->consumeMotionDown();
10822 window->consumeMotionPointerDown(1);
10823
10824 // Third finger down on the spy and window
10825 const MotionEvent thirdFingerDownEvent =
10826 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10827 .displayId(ADISPLAY_ID_DEFAULT)
10828 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010829 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10830 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10831 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010832 .build();
10833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010834 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010835 InputEventInjectionSync::WAIT_FOR_RESULT))
10836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10837 spy->consumeMotionPointerDown(1);
10838 window->consumeMotionPointerDown(2);
10839
10840 // Spy window pilfers the pointers.
10841 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010842 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10843 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010844
10845 spy->assertNoEvents();
10846 window->assertNoEvents();
10847}
10848
10849/**
10850 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10851 * other windows should be canceled. If this results in the cancellation of all pointers for some
10852 * window, then that window should receive ACTION_CANCEL.
10853 */
10854TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10855 auto spy = createSpy();
10856 spy->setFrame(Rect(0, 0, 100, 100));
10857 auto window = createForeground();
10858 window->setFrame(Rect(0, 0, 200, 200));
10859
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010860 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010861
10862 // First finger down on both spy and window
10863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010864 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010865 {10, 10}))
10866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10867 window->consumeMotionDown();
10868 spy->consumeMotionDown();
10869
10870 // Second finger down on the spy and window
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(50).y(50))
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 spy->consumeMotionPointerDown(1);
10883 window->consumeMotionPointerDown(1);
10884
10885 // Spy window pilfers the pointers.
10886 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10887 window->consumeMotionCancel();
10888
10889 spy->assertNoEvents();
10890 window->assertNoEvents();
10891}
10892
10893/**
10894 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10895 * be sent to other windows
10896 */
10897TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10898 auto spy = createSpy();
10899 spy->setFrame(Rect(0, 0, 100, 100));
10900 auto window = createForeground();
10901 window->setFrame(Rect(0, 0, 200, 200));
10902
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010903 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010904
10905 // First finger down on both window and spy
10906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010907 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010908 {10, 10}))
10909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10910 window->consumeMotionDown();
10911 spy->consumeMotionDown();
10912
10913 // Spy window pilfers the pointers.
10914 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10915 window->consumeMotionCancel();
10916
10917 // Second finger down on the window only
10918 const MotionEvent secondFingerDownEvent =
10919 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10920 .displayId(ADISPLAY_ID_DEFAULT)
10921 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010922 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10923 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010924 .build();
10925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010926 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010927 InputEventInjectionSync::WAIT_FOR_RESULT))
10928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10929 window->consumeMotionDown();
10930 window->assertNoEvents();
10931
10932 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10933 spy->consumeMotionMove();
10934 spy->assertNoEvents();
10935}
10936
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010937/**
10938 * A window on the left and a window on the right. Also, a spy window that's above all of the
10939 * windows, and spanning both left and right windows.
10940 * Send simultaneous motion streams from two different devices, one to the left window, and another
10941 * to the right window.
10942 * Pilfer from spy window.
10943 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10944 */
10945TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10946 sp<FakeWindowHandle> spy = createSpy();
10947 spy->setFrame(Rect(0, 0, 200, 200));
10948 sp<FakeWindowHandle> leftWindow = createForeground();
10949 leftWindow->setFrame(Rect(0, 0, 100, 100));
10950
10951 sp<FakeWindowHandle> rightWindow = createForeground();
10952 rightWindow->setFrame(Rect(100, 0, 200, 100));
10953
10954 constexpr int32_t stylusDeviceId = 1;
10955 constexpr int32_t touchDeviceId = 2;
10956
10957 mDispatcher->onWindowInfosChanged(
10958 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10959
10960 // Stylus down on left window and spy
10961 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10962 .deviceId(stylusDeviceId)
10963 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10964 .build());
10965 leftWindow->consumeMotionEvent(
10966 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10967 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10968
10969 // Finger down on right window and spy - but spy already has stylus
10970 mDispatcher->notifyMotion(
10971 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10972 .deviceId(touchDeviceId)
10973 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10974 .build());
10975 rightWindow->consumeMotionEvent(
10976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010977 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010978
10979 // Act: pilfer from spy. Spy is currently receiving touch events.
10980 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010981 leftWindow->consumeMotionEvent(
10982 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010983 rightWindow->consumeMotionEvent(
10984 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10985
10986 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10987 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10988 .deviceId(stylusDeviceId)
10989 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10990 .build());
10991 mDispatcher->notifyMotion(
10992 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10993 .deviceId(touchDeviceId)
10994 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10995 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010996 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010997
10998 spy->assertNoEvents();
10999 leftWindow->assertNoEvents();
11000 rightWindow->assertNoEvents();
11001}
11002
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011003TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11004 auto window = createForeground();
11005 auto spy = createSpy();
11006 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11007
11008 mDispatcher->notifyMotion(
11009 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11010 .deviceId(1)
11011 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11012 .build());
11013 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11014 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11015
11016 // Pilfer pointers from the spy window should fail.
11017 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11018 spy->assertNoEvents();
11019 window->assertNoEvents();
11020}
11021
Prabir Pradhand65552b2021-10-07 11:23:50 -070011022class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11023public:
11024 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11025 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11026 std::make_shared<FakeApplicationHandle>();
11027 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011028 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11029 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011030 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011031 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011032 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011033 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011034 overlay->setTrustedOverlay(true);
11035
11036 std::shared_ptr<FakeApplicationHandle> application =
11037 std::make_shared<FakeApplicationHandle>();
11038 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011039 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11040 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011041 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011042 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011043
11044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011045 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011046 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011047 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011048 return {std::move(overlay), std::move(window)};
11049 }
11050
11051 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011052 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011053 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011054 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011055 }
11056
11057 void sendStylusEvent(int32_t action) {
11058 NotifyMotionArgs motionArgs =
11059 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11060 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011061 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011062 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011063 }
11064};
11065
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011066using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11067
11068TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011069 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011070 ScopedSilentDeath _silentDeath;
11071
Prabir Pradhand65552b2021-10-07 11:23:50 -070011072 auto [overlay, window] = setupStylusOverlayScenario();
11073 overlay->setTrustedOverlay(false);
11074 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011075 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11076 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011077 ".* not a trusted overlay");
11078}
11079
11080TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11081 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011082 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011083
11084 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11085 overlay->consumeMotionDown();
11086 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11087 overlay->consumeMotionUp();
11088
11089 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11090 window->consumeMotionDown();
11091 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11092 window->consumeMotionUp();
11093
11094 overlay->assertNoEvents();
11095 window->assertNoEvents();
11096}
11097
11098TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11099 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011100 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011101 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011102
11103 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11104 overlay->consumeMotionDown();
11105 window->consumeMotionDown();
11106 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11107 overlay->consumeMotionUp();
11108 window->consumeMotionUp();
11109
11110 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11111 window->consumeMotionDown();
11112 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11113 window->consumeMotionUp();
11114
11115 overlay->assertNoEvents();
11116 window->assertNoEvents();
11117}
11118
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011119/**
11120 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11121 * The scenario is as follows:
11122 * - The stylus interceptor overlay is configured as a spy window.
11123 * - The stylus interceptor spy receives the start of a new stylus gesture.
11124 * - It pilfers pointers and then configures itself to no longer be a spy.
11125 * - The stylus interceptor continues to receive the rest of the gesture.
11126 */
11127TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11128 auto [overlay, window] = setupStylusOverlayScenario();
11129 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011130 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011131
11132 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11133 overlay->consumeMotionDown();
11134 window->consumeMotionDown();
11135
11136 // The interceptor pilfers the pointers.
11137 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11138 window->consumeMotionCancel();
11139
11140 // The interceptor configures itself so that it is no longer a spy.
11141 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011142 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011143
11144 // It continues to receive the rest of the stylus gesture.
11145 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11146 overlay->consumeMotionMove();
11147 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11148 overlay->consumeMotionUp();
11149
11150 window->assertNoEvents();
11151}
11152
Prabir Pradhan5735a322022-04-11 17:23:34 +000011153struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011154 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011155 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011156 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11157 std::unique_ptr<InputDispatcher>& mDispatcher;
11158
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011159 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011160 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11161
11162 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011163 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011164 ADISPLAY_ID_DEFAULT, {100, 200},
11165 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11166 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11167 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11168 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11169 }
11170
11171 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011172 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011173 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011174 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011175 mPolicyFlags);
11176 }
11177
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011178 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011179 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11180 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011181 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11182 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011183 window->setOwnerInfo(mPid, mUid);
11184 return window;
11185 }
11186};
11187
11188using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11189
11190TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011191 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011192 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011194
11195 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11196 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11197 window->consumeMotionDown();
11198
11199 setFocusedWindow(window);
11200 window->consumeFocusEvent(true);
11201
11202 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11203 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11204 window->consumeKeyDown(ADISPLAY_ID_NONE);
11205}
11206
11207TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011208 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011209 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011210 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011211
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011212 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011213 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11214 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11215
11216 setFocusedWindow(window);
11217 window->consumeFocusEvent(true);
11218
11219 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11220 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11221 window->assertNoEvents();
11222}
11223
11224TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011225 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011226 auto window = owner.createWindow("Owned window");
11227 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011228 spy->setSpy(true);
11229 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011230 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011231
11232 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11233 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11234 spy->consumeMotionDown();
11235 window->consumeMotionDown();
11236}
11237
11238TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011239 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011240 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011241
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011242 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011243 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011244 randosSpy->setSpy(true);
11245 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011246 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011247
11248 // The event is targeted at owner's window, so injection should succeed, but the spy should
11249 // not receive the event.
11250 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11251 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11252 randosSpy->assertNoEvents();
11253 window->consumeMotionDown();
11254}
11255
11256TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011257 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011258 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011259
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011260 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011261 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011262 randosSpy->setSpy(true);
11263 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011264 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011265
11266 // A user that has injection permission can inject into any window.
11267 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011268 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011269 ADISPLAY_ID_DEFAULT));
11270 randosSpy->consumeMotionDown();
11271 window->consumeMotionDown();
11272
11273 setFocusedWindow(randosSpy);
11274 randosSpy->consumeFocusEvent(true);
11275
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011276 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011277 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11278 window->assertNoEvents();
11279}
11280
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011281TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011282 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011283 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011284
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011285 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011286 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011287 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11288 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011289 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011290
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011291 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011292 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11293 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11294 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011295 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011296}
11297
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011298using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11299
11300TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11302
11303 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11304 ADISPLAY_ID_DEFAULT);
11305 left->setFrame(Rect(0, 0, 100, 100));
11306 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11307 "Right Window", ADISPLAY_ID_DEFAULT);
11308 right->setFrame(Rect(100, 0, 200, 100));
11309 sp<FakeWindowHandle> spy =
11310 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11311 spy->setFrame(Rect(0, 0, 200, 100));
11312 spy->setTrustedOverlay(true);
11313 spy->setSpy(true);
11314
11315 mDispatcher->onWindowInfosChanged(
11316 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11317
11318 // Hover into the left window.
11319 mDispatcher->notifyMotion(
11320 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11321 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11322 .build());
11323
11324 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11325 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11326
11327 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11328 /*pointerId=*/0));
11329 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11330 /*pointerId=*/0));
11331 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11332 /*pointerId=*/0));
11333
11334 // Hover move to the right window.
11335 mDispatcher->notifyMotion(
11336 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11337 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11338 .build());
11339
11340 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11341 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11342 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11343
11344 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11345 /*pointerId=*/0));
11346 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11347 /*pointerId=*/0));
11348 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11349 /*pointerId=*/0));
11350
11351 // Stop hovering.
11352 mDispatcher->notifyMotion(
11353 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11354 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11355 .build());
11356
11357 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11358 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11359
11360 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11361 /*pointerId=*/0));
11362 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11363 /*pointerId=*/0));
11364 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11365 /*pointerId=*/0));
11366}
11367
11368TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11370
11371 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11372 ADISPLAY_ID_DEFAULT);
11373 left->setFrame(Rect(0, 0, 100, 100));
11374 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11375 "Right Window", ADISPLAY_ID_DEFAULT);
11376 right->setFrame(Rect(100, 0, 200, 100));
11377 sp<FakeWindowHandle> spy =
11378 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11379 spy->setFrame(Rect(0, 0, 200, 100));
11380 spy->setTrustedOverlay(true);
11381 spy->setSpy(true);
11382
11383 mDispatcher->onWindowInfosChanged(
11384 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11385
11386 // First pointer down on left window.
11387 mDispatcher->notifyMotion(
11388 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11389 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11390 .build());
11391
11392 left->consumeMotionDown();
11393 spy->consumeMotionDown();
11394
11395 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11396 /*pointerId=*/0));
11397 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11398 /*pointerId=*/0));
11399 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11400 /*pointerId=*/0));
11401
11402 // Second pointer down on right window.
11403 mDispatcher->notifyMotion(
11404 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11405 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11406 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11407 .build());
11408
11409 left->consumeMotionMove();
11410 right->consumeMotionDown();
11411 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11412
11413 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11414 /*pointerId=*/0));
11415 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11416 /*pointerId=*/0));
11417 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11418 /*pointerId=*/0));
11419 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11420 /*pointerId=*/1));
11421 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11422 /*pointerId=*/1));
11423 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11424 /*pointerId=*/1));
11425
11426 // Second pointer up.
11427 mDispatcher->notifyMotion(
11428 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11429 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11430 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11431 .build());
11432
11433 left->consumeMotionMove();
11434 right->consumeMotionUp();
11435 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11436
11437 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11438 /*pointerId=*/0));
11439 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11440 /*pointerId=*/0));
11441 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11442 /*pointerId=*/0));
11443 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11444 /*pointerId=*/1));
11445 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11446 /*pointerId=*/1));
11447 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11448 /*pointerId=*/1));
11449
11450 // First pointer up.
11451 mDispatcher->notifyMotion(
11452 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11453 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11454 .build());
11455
11456 left->consumeMotionUp();
11457 spy->consumeMotionUp();
11458
11459 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11460 /*pointerId=*/0));
11461 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11462 /*pointerId=*/0));
11463 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11464 /*pointerId=*/0));
11465}
11466
11467TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11469
11470 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11471 ADISPLAY_ID_DEFAULT);
11472 left->setFrame(Rect(0, 0, 100, 100));
11473 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11474 "Right Window", ADISPLAY_ID_DEFAULT);
11475 right->setFrame(Rect(100, 0, 200, 100));
11476
11477 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11478
11479 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11480 /*pointerId=*/0));
11481 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11482 /*pointerId=*/0));
11483
11484 // Hover move into the window.
11485 mDispatcher->notifyMotion(
11486 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11487 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11488 .rawXCursorPosition(50)
11489 .rawYCursorPosition(50)
11490 .deviceId(DEVICE_ID)
11491 .build());
11492
11493 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11494
11495 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11496 /*pointerId=*/0));
11497
11498 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11499 mDispatcher->notifyMotion(
11500 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11501 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11502 .rawXCursorPosition(51)
11503 .rawYCursorPosition(50)
11504 .deviceId(SECOND_DEVICE_ID)
11505 .build());
11506
11507 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11508 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11509
11510 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11511 // a HOVER_EXIT from the first device.
11512 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11513 /*pointerId=*/0));
11514 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11515 SECOND_DEVICE_ID,
11516 /*pointerId=*/0));
11517
11518 // Move the mouse outside the window. Document the current behavior, where the window does not
11519 // receive HOVER_EXIT even though the mouse left the window.
11520 mDispatcher->notifyMotion(
11521 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11522 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11523 .rawXCursorPosition(150)
11524 .rawYCursorPosition(50)
11525 .deviceId(SECOND_DEVICE_ID)
11526 .build());
11527
11528 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11529 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11530 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11531 /*pointerId=*/0));
11532 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11533 SECOND_DEVICE_ID,
11534 /*pointerId=*/0));
11535}
11536
Garfield Tane84e6f92019-08-29 17:28:41 -070011537} // namespace android::inputdispatcher