blob: ff3eff16eb46a8865340cc86342478a9ba82da58 [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"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000019#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Cody Heiner166a5af2023-07-07 12:25:00 -070021#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070022#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080023#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080024#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070025#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070026#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000027#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000028#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080030#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070033#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080035#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080038#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070039#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080041#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050044using android::gui::FocusRequest;
45using android::gui::TouchOcclusionMode;
46using android::gui::WindowInfo;
47using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080048using android::os::InputEventInjectionResult;
49using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080050
Garfield Tane84e6f92019-08-29 17:28:41 -070051namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080054using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070056namespace {
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000059static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080060
61// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000062static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080063static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
Jeff Brownf086ddb2014-02-11 14:28:48 -080065// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000066static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
67static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080068
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000069// Ensure common actions are interchangeable between keys and motions for convenience.
70static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
71static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080072static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
73static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
74static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
75static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070076static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080077static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070078static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080079static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080080static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081/**
82 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
83 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
84 * index 0) is the new pointer going down. The same pointer could have been placed at a different
85 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
86 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
87 * pointer id=0 leaves but the pointer id=1 remains.
88 */
89static constexpr int32_t POINTER_0_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080091static constexpr int32_t POINTER_1_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000093static constexpr int32_t POINTER_2_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000095static constexpr int32_t POINTER_3_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000097static constexpr int32_t POINTER_0_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080099static constexpr int32_t POINTER_1_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000101static constexpr int32_t POINTER_2_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103
Antonio Kantek15beb512022-06-13 22:35:41 +0000104// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000105static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000106static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000111
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000114
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800115static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
116
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700117/**
118 * If we expect to receive the event, the timeout can be made very long. When the test are running
119 * correctly, we will actually never wait until the end of the timeout because the wait will end
120 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
121 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
122 * developer can see the failure quickly (on human scale).
123 */
124static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
125/**
126 * When no event is expected, we can have a very short timeout. A large value here would slow down
127 * the tests. In the unlikely event of system being too slow, the event may still be present but the
128 * timeout would complete before it is consumed. This would result in test flakiness. If this
129 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
130 * would get noticed and addressed quickly.
131 */
132static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
133
Arthur Hungc539dbb2022-12-08 07:45:36 +0000134static constexpr int expectedWallpaperFlags =
135 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
136
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800137using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
138
Gang Wang342c9272020-01-13 13:15:04 -0500139/**
140 * Return a DOWN key event with KEYCODE_A.
141 */
142static KeyEvent getTestKeyEvent() {
143 KeyEvent event;
144
Garfield Tanfbe732e2020-01-24 11:26:14 -0800145 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
146 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
147 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500148 return event;
149}
150
Michael Wrightd02c5b62014-02-10 15:10:22 -0800151// --- FakeInputDispatcherPolicy ---
152
153class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000154 struct AnrResult {
155 sp<IBinder> token{};
156 gui::Pid pid{gui::Pid::INVALID};
157 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800158
Michael Wrightd02c5b62014-02-10 15:10:22 -0800159public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000160 FakeInputDispatcherPolicy() = default;
161 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800162
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800163 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700165 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700166 EXPECT_EQ(event.getDisplayId(), args.displayId);
167
168 const auto& keyEvent = static_cast<const KeyEvent&>(event);
169 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
170 EXPECT_EQ(keyEvent.getAction(), args.action);
171 });
Jackal Guof9696682018-10-05 12:23:23 +0800172 }
173
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700174 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
175 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700176 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700177 EXPECT_EQ(event.getDisplayId(), args.displayId);
178
179 const auto& motionEvent = static_cast<const MotionEvent&>(event);
180 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
181 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000182 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700186 });
Jackal Guof9696682018-10-05 12:23:23 +0800187 }
188
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700189 void assertFilterInputEventWasNotCalled() {
190 std::scoped_lock lock(mLock);
191 ASSERT_EQ(nullptr, mFilteredEvent);
192 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700195 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800196 ASSERT_TRUE(mConfigurationChangedTime)
197 << "Timed out waiting for configuration changed call";
198 ASSERT_EQ(*mConfigurationChangedTime, when);
199 mConfigurationChangedTime = std::nullopt;
200 }
201
202 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700203 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800204 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800205 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800206 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
207 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
208 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
209 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
210 mLastNotifySwitch = std::nullopt;
211 }
212
chaviwfd6d3512019-03-25 13:23:49 -0700213 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700214 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800215 ASSERT_EQ(touchedToken, mOnPointerDownToken);
216 mOnPointerDownToken.clear();
217 }
218
219 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700220 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800221 ASSERT_TRUE(mOnPointerDownToken == nullptr)
222 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700223 }
224
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700225 // This function must be called soon after the expected ANR timer starts,
226 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700228 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500229 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800230 std::unique_lock lock(mLock);
231 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500232 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800233 ASSERT_NO_FATAL_FAILURE(
234 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500235 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700236 }
237
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000238 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800239 const sp<WindowInfoHandle>& window) {
240 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
241 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
242 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 }
244
Prabir Pradhanedd96402022-02-15 01:46:16 -0800245 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
246 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000247 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800248 std::unique_lock lock(mLock);
249 android::base::ScopedLockAssertion assumeLocked(mLock);
250 AnrResult result;
251 ASSERT_NO_FATAL_FAILURE(result =
252 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000253 ASSERT_EQ(expectedToken, result.token);
254 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500255 }
256
Prabir Pradhanedd96402022-02-15 01:46:16 -0800257 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000258 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500259 std::unique_lock lock(mLock);
260 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800261 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
262 const auto& [token, _] = result;
263 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000264 }
265
Prabir Pradhanedd96402022-02-15 01:46:16 -0800266 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000267 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800268 std::unique_lock lock(mLock);
269 android::base::ScopedLockAssertion assumeLocked(mLock);
270 AnrResult result;
271 ASSERT_NO_FATAL_FAILURE(
272 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000273 ASSERT_EQ(expectedToken, result.token);
274 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800275 }
276
277 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000278 sp<IBinder> getResponsiveWindowToken() {
279 std::unique_lock lock(mLock);
280 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
282 const auto& [token, _] = result;
283 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700284 }
285
286 void assertNotifyAnrWasNotCalled() {
287 std::scoped_lock lock(mLock);
288 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800289 ASSERT_TRUE(mAnrWindows.empty());
290 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500291 << "ANR was not called, but please also consume the 'connection is responsive' "
292 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700293 }
294
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000295 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800296 std::unique_lock lock(mLock);
297 base::ScopedLockAssertion assumeLocked(mLock);
298
299 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
300 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000301 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800302 enabled;
303 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000304 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
305 << ") to be called.";
306 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800307 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000308 auto request = *mPointerCaptureRequest;
309 mPointerCaptureRequest.reset();
310 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800311 }
312
313 void assertSetPointerCaptureNotCalled() {
314 std::unique_lock lock(mLock);
315 base::ScopedLockAssertion assumeLocked(mLock);
316
317 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800321 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000322 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800323 }
324
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700325 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
326 const sp<IBinder>& targetToken) {
327 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800328 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800329 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800330 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800331 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800332 }
333
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800334 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
335 std::unique_lock lock(mLock);
336 base::ScopedLockAssertion assumeLocked(mLock);
337 std::optional<sp<IBinder>> receivedToken =
338 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
339 mNotifyInputChannelBroken);
340 ASSERT_TRUE(receivedToken.has_value());
341 ASSERT_EQ(token, *receivedToken);
342 }
343
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800344 /**
345 * Set policy timeout. A value of zero means next key will not be intercepted.
346 */
347 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
348 mInterceptKeyTimeout = timeout;
349 }
350
Josep del Riob3981622023-04-18 15:49:45 +0000351 void assertUserActivityPoked() {
352 std::scoped_lock lock(mLock);
353 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
354 }
355
356 void assertUserActivityNotPoked() {
357 std::scoped_lock lock(mLock);
358 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
359 }
360
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000361 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000362 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
363 }
364
365 void assertNotifyDeviceInteractionWasNotCalled() {
366 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
367 }
368
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700370 std::mutex mLock;
371 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
372 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
373 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
374 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800375
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000377
378 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800379
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700380 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700381 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800382 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
383 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700384 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800385 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
386 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700387
arthurhungf452d0b2021-01-06 00:19:52 +0800388 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800389 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000390 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800391
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800392 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
393
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000394 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000395
Prabir Pradhanedd96402022-02-15 01:46:16 -0800396 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
397 // for a specific container to become non-empty. When the container is non-empty, return the
398 // first entry from the container and erase it.
399 template <class T>
400 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
401 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
402 // If there is an ANR, Dispatcher won't be idle because there are still events
403 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
404 // before checking if ANR was called.
405 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
406 // to provide it some time to act. 100ms seems reasonable.
407 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
408 const std::chrono::time_point start = std::chrono::steady_clock::now();
409 std::optional<T> token =
410 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
411 if (!token.has_value()) {
412 ADD_FAILURE() << "Did not receive the ANR callback";
413 return {};
414 }
415
416 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
417 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
418 // the dispatcher started counting before this function was called
419 if (std::chrono::abs(timeout - waited) > 100ms) {
420 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
421 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
422 << "ms, but waited "
423 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
424 << "ms instead";
425 }
426 return *token;
427 }
428
429 template <class T>
430 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
431 std::queue<T>& storage,
432 std::unique_lock<std::mutex>& lock,
433 std::condition_variable& condition)
434 REQUIRES(mLock) {
435 condition.wait_for(lock, timeout,
436 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
437 if (storage.empty()) {
438 ADD_FAILURE() << "Did not receive the expected callback";
439 return std::nullopt;
440 }
441 T item = storage.front();
442 storage.pop();
443 return std::make_optional(item);
444 }
445
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600446 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700447 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800448 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800449 }
450
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000451 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800452 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700453 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 ASSERT_TRUE(pid.has_value());
455 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700456 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500457 }
458
Prabir Pradhanedd96402022-02-15 01:46:16 -0800459 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000460 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500461 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800462 ASSERT_TRUE(pid.has_value());
463 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500464 mNotifyAnr.notify_all();
465 }
466
467 void notifyNoFocusedWindowAnr(
468 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
469 std::scoped_lock lock(mLock);
470 mAnrApplications.push(applicationHandle);
471 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800472 }
473
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800474 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
475 std::scoped_lock lock(mLock);
476 mBrokenInputChannels.push(connectionToken);
477 mNotifyInputChannelBroken.notify_all();
478 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800479
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600480 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700481
Chris Yef59a2f42020-10-16 12:55:26 -0700482 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
483 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
484 const std::vector<float>& values) override {}
485
486 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
487 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000488
Chris Yefb552902021-02-03 17:18:37 -0800489 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
490
Prabir Pradhana41d2442023-04-20 21:30:40 +0000491 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700492 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000493 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700494 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000495 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
496 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800497 break;
498 }
499
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700500 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000501 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
502 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800503 break;
504 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700505 default: {
506 ADD_FAILURE() << "Should only filter keys or motions";
507 break;
508 }
Jackal Guof9696682018-10-05 12:23:23 +0800509 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800510 return true;
511 }
512
Prabir Pradhana41d2442023-04-20 21:30:40 +0000513 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
514 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800515 // Clear intercept state when we handled the event.
516 mInterceptKeyTimeout = 0ms;
517 }
518 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800519
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600520 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521
Prabir Pradhana41d2442023-04-20 21:30:40 +0000522 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800523 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
524 // Clear intercept state so we could dispatch the event in next wake.
525 mInterceptKeyTimeout = 0ms;
526 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 }
528
Prabir Pradhana41d2442023-04-20 21:30:40 +0000529 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
530 uint32_t) override {
531 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800532 }
533
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600534 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
535 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700536 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800537 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
538 * essentially a passthrough for notifySwitch.
539 */
Harry Cutts33476232023-01-30 19:57:29 +0000540 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 }
542
Josep del Riob3981622023-04-18 15:49:45 +0000543 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
544 std::scoped_lock lock(mLock);
545 mPokedUserActivity = true;
546 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800547
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600548 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700549 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700550 mOnPointerDownToken = newToken;
551 }
552
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000553 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800554 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000555 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800556 mPointerCaptureChangedCondition.notify_all();
557 }
558
arthurhungf452d0b2021-01-06 00:19:52 +0800559 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
560 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800561 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800562 mDropTargetWindowToken = token;
563 }
564
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000565 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000566 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000567 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
568 }
569
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700570 void assertFilterInputEventWasCalledInternal(
571 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700572 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800573 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700574 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800575 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800576 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700578} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580// --- InputDispatcherTest ---
581
582class InputDispatcherTest : public testing::Test {
583protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700585 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000587 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000588 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
589 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000590 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000591 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700592 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000595 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700596 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000597 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700600
601 /**
602 * Used for debugging when writing the test
603 */
604 void dumpDispatcherState() {
605 std::string dump;
606 mDispatcher->dump(dump);
607 std::stringstream ss(dump);
608 std::string to;
609
610 while (std::getline(ss, to, '\n')) {
611 ALOGE("%s", to.c_str());
612 }
613 }
Vishnu Nair958da932020-08-21 17:12:37 -0700614
Chavi Weingarten847e8512023-03-29 00:26:09 +0000615 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700616 FocusRequest request;
617 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000618 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700619 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
620 request.displayId = window->getInfo()->displayId;
621 mDispatcher->setFocusedWindow(request);
622 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623};
624
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
626 KeyEvent event;
627
628 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800629 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
630 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600632 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800633 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000634 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000635 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636 << "Should reject key events with undefined action.";
637
638 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800639 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
640 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600641 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800642 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000643 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000644 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800645 << "Should reject key events with ACTION_MULTIPLE.";
646}
647
648TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
649 MotionEvent event;
650 PointerProperties pointerProperties[MAX_POINTERS + 1];
651 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800652 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 pointerProperties[i].clear();
654 pointerProperties[i].id = i;
655 pointerCoords[i].clear();
656 }
657
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800658 // Some constants commonly used below
659 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
660 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
661 constexpr int32_t metaState = AMETA_NONE;
662 constexpr MotionClassification classification = MotionClassification::NONE;
663
chaviw9eaa22c2020-07-01 16:21:27 -0700664 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800666 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000667 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700668 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700669 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
670 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000671 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800672 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000673 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000674 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800675 << "Should reject motion events with undefined action.";
676
677 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800678 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800679 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
680 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
681 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
682 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000683 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800684 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000685 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000686 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687 << "Should reject motion events with pointer down index too large.";
688
Garfield Tanfbe732e2020-01-24 11:26:14 -0800689 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700690 AMOTION_EVENT_ACTION_POINTER_DOWN |
691 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700692 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
693 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700694 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000695 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject motion events with pointer down index too small.";
700
701 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800702 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800703 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
704 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
705 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
706 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000707 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800708 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000709 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000710 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800711 << "Should reject motion events with pointer up index too large.";
712
Garfield Tanfbe732e2020-01-24 11:26:14 -0800713 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700714 AMOTION_EVENT_ACTION_POINTER_UP |
715 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700716 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
717 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700718 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000719 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800720 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000721 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000722 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800723 << "Should reject motion events with pointer up index too small.";
724
725 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
727 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700728 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700729 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
730 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000731 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject motion events with 0 pointers.";
736
Garfield Tanfbe732e2020-01-24 11:26:14 -0800737 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
738 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700739 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700740 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
741 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000742 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000744 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000745 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800746 << "Should reject motion events with more than MAX_POINTERS pointers.";
747
748 // Rejects motion events with invalid pointer ids.
749 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800750 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
751 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700752 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700753 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
754 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000755 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800756 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000757 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000758 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800759 << "Should reject motion events with pointer ids less than 0.";
760
761 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800762 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
763 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700764 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700765 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
766 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000767 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800768 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000769 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000770 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800771 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
772
773 // Rejects motion events with duplicate pointer ids.
774 pointerProperties[0].id = 1;
775 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800776 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
777 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700778 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700779 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
780 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000781 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000784 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 << "Should reject motion events with duplicate pointer ids.";
786}
787
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800788/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
789
790TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
791 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000792 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800793 ASSERT_TRUE(mDispatcher->waitForIdle());
794
795 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
796}
797
798TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000799 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
800 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000801 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800802
803 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
804 args.policyFlags |= POLICY_FLAG_TRUSTED;
805 mFakePolicy->assertNotifySwitchWasCalled(args);
806}
807
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700808namespace {
809
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700810static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700811// Default input dispatching timeout if there is no focused application or paused window
812// from which to determine an appropriate dispatching timeout.
813static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
814 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
815 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800816
817class FakeApplicationHandle : public InputApplicationHandle {
818public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700819 FakeApplicationHandle() {
820 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700821 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500822 mInfo.dispatchingTimeoutMillis =
823 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700824 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800825 virtual ~FakeApplicationHandle() {}
826
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000827 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700828
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500829 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
830 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700831 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800832};
833
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800834class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800835public:
Garfield Tan15601662020-09-22 15:32:38 -0700836 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800837 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700838 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800839 }
840
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700841 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700842 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700843 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700844 if (!consumeSeq) {
845 return nullptr;
846 }
847 finishEvent(*consumeSeq);
848 return event;
849 }
850
851 /**
852 * Receive an event without acknowledging it.
853 * Return the sequence number that could later be used to send finished signal.
854 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700855 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
856 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800857 uint32_t consumeSeq;
858 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800859
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800860 std::chrono::time_point start = std::chrono::steady_clock::now();
861 status_t status = WOULD_BLOCK;
862 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000863 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800864 &event);
865 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 break;
868 }
869 }
870
871 if (status == WOULD_BLOCK) {
872 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800874 }
875
876 if (status != OK) {
877 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800879 }
880 if (event == nullptr) {
881 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 if (outEvent != nullptr) {
885 *outEvent = event;
886 }
887 return consumeSeq;
888 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800889
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700890 /**
891 * To be used together with "receiveEvent" to complete the consumption of an event.
892 */
893 void finishEvent(uint32_t consumeSeq) {
894 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
895 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896 }
897
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000898 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
899 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
900 ASSERT_EQ(OK, status);
901 }
902
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700903 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000904 std::optional<int32_t> expectedDisplayId,
905 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700906 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800907
908 ASSERT_NE(nullptr, event) << mName.c_str()
909 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800910 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700911 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
912 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000914 if (expectedDisplayId.has_value()) {
915 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
916 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800917
Tiger Huang8664f8c2018-10-11 19:14:35 +0800918 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700919 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800920 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700921 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000922 if (expectedFlags.has_value()) {
923 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
924 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800925 break;
926 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700927 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800928 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700929 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000930 if (expectedFlags.has_value()) {
931 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
932 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800933 break;
934 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700935 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100936 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
937 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700938 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800939 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
940 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700941 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000942 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
943 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700944 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800945 FAIL() << "Use 'consumeDragEvent' for DRAG events";
946 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800947 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800948 }
949
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800950 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700951 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800952
953 if (event == nullptr) {
954 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
955 return nullptr;
956 }
957
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 if (event->getType() != InputEventType::MOTION) {
959 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800960 return nullptr;
961 }
962 return static_cast<MotionEvent*>(event);
963 }
964
965 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
966 MotionEvent* motionEvent = consumeMotion();
967 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
968 ASSERT_THAT(*motionEvent, matcher);
969 }
970
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100971 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700972 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100973 ASSERT_NE(nullptr, event) << mName.c_str()
974 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700975 ASSERT_EQ(InputEventType::FOCUS, event->getType())
976 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100977
978 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
979 << mName.c_str() << ": event displayId should always be NONE.";
980
981 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
982 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100983 }
984
Prabir Pradhan99987712020-11-10 18:43:05 -0800985 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700986 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800987 ASSERT_NE(nullptr, event) << mName.c_str()
988 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
990 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800991
992 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
993 << mName.c_str() << ": event displayId should always be NONE.";
994
995 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
996 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
997 }
998
arthurhungb89ccb02020-12-30 16:19:01 +0800999 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001000 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001001 ASSERT_NE(nullptr, event) << mName.c_str()
1002 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001003 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001004
1005 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1006 << mName.c_str() << ": event displayId should always be NONE.";
1007
1008 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1009 EXPECT_EQ(isExiting, dragEvent.isExiting());
1010 EXPECT_EQ(x, dragEvent.getX());
1011 EXPECT_EQ(y, dragEvent.getY());
1012 }
1013
Antonio Kantekf16f2832021-09-28 04:39:20 +00001014 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001015 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001016 ASSERT_NE(nullptr, event) << mName.c_str()
1017 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001018 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1019 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001020
1021 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1022 << mName.c_str() << ": event displayId should always be NONE.";
1023 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1024 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1025 }
1026
chaviwd1c23182019-12-20 18:44:56 -08001027 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001028 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001029 if (event == nullptr) {
1030 return;
1031 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001032 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001033 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1034 ADD_FAILURE() << "Received key event "
1035 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001036 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001037 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1038 ADD_FAILURE() << "Received motion event "
1039 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001040 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001041 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1042 ADD_FAILURE() << "Received focus event, hasFocus = "
1043 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001045 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1046 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1047 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001048 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001049 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1050 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1051 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 }
1053 FAIL() << mName.c_str()
1054 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001055 }
1056
1057 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1058
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001059 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1060
chaviwd1c23182019-12-20 18:44:56 -08001061protected:
1062 std::unique_ptr<InputConsumer> mConsumer;
1063 PreallocatedInputEventFactory mEventFactory;
1064
1065 std::string mName;
1066};
1067
chaviw3277faf2021-05-19 16:45:23 -05001068class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001069public:
1070 static const int32_t WIDTH = 600;
1071 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001072
Chris Yea209fde2020-07-22 13:54:51 -07001073 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001074 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001075 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001076 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001077 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001078 base::Result<std::unique_ptr<InputChannel>> channel =
1079 dispatcher->createInputChannel(name);
1080 token = (*channel)->getConnectionToken();
1081 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001082 }
1083
1084 inputApplicationHandle->updateInfo();
1085 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1086
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001087 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001088 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001089 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001090 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001091 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001092 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001093 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001094 mInfo.globalScaleFactor = 1.0;
1095 mInfo.touchableRegion.clear();
1096 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001097 mInfo.ownerPid = WINDOW_PID;
1098 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001099 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001100 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001103 sp<FakeWindowHandle> clone(int32_t displayId) {
1104 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1105 handle->mInfo = mInfo;
1106 handle->mInfo.displayId = displayId;
1107 handle->mInfo.id = sId++;
1108 handle->mInputReceiver = mInputReceiver;
1109 return handle;
1110 }
1111
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001112 void setTouchable(bool touchable) {
1113 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1114 }
chaviwd1c23182019-12-20 18:44:56 -08001115
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001116 void setFocusable(bool focusable) {
1117 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1118 }
1119
1120 void setVisible(bool visible) {
1121 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1122 }
Vishnu Nair958da932020-08-21 17:12:37 -07001123
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001124 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001125 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001126 }
1127
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001128 void setPaused(bool paused) {
1129 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1130 }
1131
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001132 void setPreventSplitting(bool preventSplitting) {
1133 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 }
1135
1136 void setSlippery(bool slippery) {
1137 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1138 }
1139
1140 void setWatchOutsideTouch(bool watchOutside) {
1141 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1142 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001143
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001144 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1145
1146 void setInterceptsStylus(bool interceptsStylus) {
1147 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1148 }
1149
1150 void setDropInput(bool dropInput) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1152 }
1153
1154 void setDropInputIfObscured(bool dropInputIfObscured) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1156 }
1157
1158 void setNoInputChannel(bool noInputChannel) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1160 }
1161
Josep del Riob3981622023-04-18 15:49:45 +00001162 void setDisableUserActivity(bool disableUserActivity) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1164 }
1165
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001166 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1167
chaviw3277faf2021-05-19 16:45:23 -05001168 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001169
Bernardo Rufino7393d172021-02-26 13:56:11 +00001170 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1171
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001172 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001173 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001174 mInfo.touchableRegion.clear();
1175 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001176
1177 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1178 ui::Transform translate;
1179 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1180 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001181 }
1182
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001183 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setIsWallpaper(bool isWallpaper) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1187 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001188
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001189 void setDupTouchToWallpaper(bool hasWallpaper) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1191 }
chaviwd1c23182019-12-20 18:44:56 -08001192
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001193 void setTrustedOverlay(bool trustedOverlay) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1195 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001196
chaviw9eaa22c2020-07-01 16:21:27 -07001197 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1198 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1199 }
1200
1201 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001202
yunho.shinf4a80b82020-11-16 21:13:57 +09001203 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1204
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001205 KeyEvent* consumeKey() {
1206 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1207 if (event == nullptr) {
1208 ADD_FAILURE() << "Consume failed : no event";
1209 return nullptr;
1210 }
1211 if (event->getType() != InputEventType::KEY) {
1212 ADD_FAILURE() << "Instead of key event, got " << *event;
1213 return nullptr;
1214 }
1215 return static_cast<KeyEvent*>(event);
1216 }
1217
1218 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1219 KeyEvent* keyEvent = consumeKey();
1220 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1221 ASSERT_THAT(*keyEvent, matcher);
1222 }
1223
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001224 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001225 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001226 }
1227
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001228 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001229 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001230 }
1231
Svet Ganov5d3bc372020-01-26 23:11:07 -08001232 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001233 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001234 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1235 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001236 }
1237
1238 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001239 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001240 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1241 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001242 }
1243
1244 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001245 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001246 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1247 }
1248
1249 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1250 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001251 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001252 expectedFlags);
1253 }
1254
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001256 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1257 int32_t expectedFlags = 0) {
1258 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1259 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001260 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
1265 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1266 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001267 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001268 }
1269
1270 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001272 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001273 expectedFlags);
1274 }
1275
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001276 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1277 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001278 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001279 expectedFlags);
1280 }
1281
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001282 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1283 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001284 MotionEvent* motionEvent = consumeMotion();
1285 ASSERT_NE(nullptr, motionEvent);
1286 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1287 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1288 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001289 }
1290
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001291 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1292 ASSERT_NE(mInputReceiver, nullptr)
1293 << "Cannot consume events from a window with no receiver";
1294 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1295 }
1296
Prabir Pradhan99987712020-11-10 18:43:05 -08001297 void consumeCaptureEvent(bool hasCapture) {
1298 ASSERT_NE(mInputReceiver, nullptr)
1299 << "Cannot consume events from a window with no receiver";
1300 mInputReceiver->consumeCaptureEvent(hasCapture);
1301 }
1302
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001303 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1304 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001305 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001306 ASSERT_THAT(*motionEvent, matcher);
1307 }
1308
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001309 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001310 std::optional<int32_t> expectedDisplayId,
1311 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001312 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1313 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1314 expectedFlags);
1315 }
1316
arthurhungb89ccb02020-12-30 16:19:01 +08001317 void consumeDragEvent(bool isExiting, float x, float y) {
1318 mInputReceiver->consumeDragEvent(isExiting, x, y);
1319 }
1320
Antonio Kantekf16f2832021-09-28 04:39:20 +00001321 void consumeTouchModeEvent(bool inTouchMode) {
1322 ASSERT_NE(mInputReceiver, nullptr)
1323 << "Cannot consume events from a window with no receiver";
1324 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1325 }
1326
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001327 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001328 if (mInputReceiver == nullptr) {
1329 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1330 return std::nullopt;
1331 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001332 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001333 }
1334
1335 void finishEvent(uint32_t sequenceNum) {
1336 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1337 mInputReceiver->finishEvent(sequenceNum);
1338 }
1339
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001340 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1341 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1342 mInputReceiver->sendTimeline(inputEventId, timeline);
1343 }
1344
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001345 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001346 if (mInputReceiver == nullptr) {
1347 return nullptr;
1348 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001349 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001350 }
1351
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001352 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001353 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001354 if (event == nullptr) {
1355 ADD_FAILURE() << "Consume failed : no event";
1356 return nullptr;
1357 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001358 if (event->getType() != InputEventType::MOTION) {
1359 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001360 return nullptr;
1361 }
1362 return static_cast<MotionEvent*>(event);
1363 }
1364
Arthur Hungb92218b2018-08-14 12:00:21 +08001365 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001366 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001367 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 return; // Can't receive events if the window does not have input channel
1369 }
1370 ASSERT_NE(nullptr, mInputReceiver)
1371 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001372 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001373 }
1374
chaviwaf87b3e2019-10-01 16:59:28 -07001375 sp<IBinder> getToken() { return mInfo.token; }
1376
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001377 const std::string& getName() { return mName; }
1378
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001379 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001380 mInfo.ownerPid = ownerPid;
1381 mInfo.ownerUid = ownerUid;
1382 }
1383
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001384 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001385
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001386 void destroyReceiver() { mInputReceiver = nullptr; }
1387
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001388 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1389
chaviwd1c23182019-12-20 18:44:56 -08001390private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001391 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001392 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001394 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001395 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001396};
1397
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001398std::atomic<int32_t> FakeWindowHandle::sId{1};
1399
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001400class FakeMonitorReceiver {
1401public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001402 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001403 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001404 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001405 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1406 }
1407
1408 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1409
1410 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1411 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1412 expectedFlags);
1413 }
1414
1415 std::optional<int32_t> receiveEvent() {
1416 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1417 }
1418
1419 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1420
1421 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1422 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1423 expectedDisplayId, expectedFlags);
1424 }
1425
1426 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1427 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1428 expectedDisplayId, expectedFlags);
1429 }
1430
1431 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1432 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1433 expectedDisplayId, expectedFlags);
1434 }
1435
1436 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1437 mInputReceiver->consumeMotionEvent(
1438 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1439 WithDisplayId(expectedDisplayId),
1440 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1441 }
1442
1443 void consumeMotionPointerDown(int32_t pointerIdx) {
1444 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1445 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1446 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1447 /*expectedFlags=*/0);
1448 }
1449
1450 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1451 mInputReceiver->consumeMotionEvent(matcher);
1452 }
1453
1454 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1455
1456 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1457
1458private:
1459 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1460};
1461
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001462static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001463 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001464 int32_t displayId = ADISPLAY_ID_NONE,
1465 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001466 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001467 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001468 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001469 KeyEvent event;
1470 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1471
1472 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001473 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001474 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1475 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001476
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001477 if (!allowKeyRepeat) {
1478 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1479 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001480 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001481 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001482}
1483
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001484static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1485 InputEventInjectionResult result =
1486 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1487 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1488 if (result != InputEventInjectionResult::TIMED_OUT) {
1489 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1490 }
1491}
1492
1493static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001494 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001495 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001496}
1497
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1499// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1500// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001501static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1502 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001503 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001504 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001505 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001506}
1507
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001508static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001509 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001510 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001511}
1512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001514 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001515 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001516 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001517 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1519 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001520}
1521
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001522static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001523 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1524 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001525 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001526 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1527 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001529 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001530 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001531 MotionEventBuilder motionBuilder =
1532 MotionEventBuilder(action, source)
1533 .displayId(displayId)
1534 .eventTime(eventTime)
1535 .rawXCursorPosition(cursorPosition.x)
1536 .rawYCursorPosition(cursorPosition.y)
1537 .pointer(
1538 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1539 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1540 motionBuilder.downTime(eventTime);
1541 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001542
1543 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001544 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1545 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001546}
1547
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001548static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1549 int32_t displayId,
1550 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001551 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001552}
1553
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001554static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1555 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001556 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001557 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001558}
1559
Jackal Guof9696682018-10-05 12:23:23 +08001560static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1561 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1562 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001563 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001564 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1565 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001566
1567 return args;
1568}
1569
Josep del Riob3981622023-04-18 15:49:45 +00001570static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1571 int32_t displayId = ADISPLAY_ID_NONE) {
1572 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1573 // Define a valid key event.
1574 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001575 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001576 currentTime);
1577
1578 return args;
1579}
1580
1581static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1582 int32_t displayId = ADISPLAY_ID_NONE) {
1583 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1584 // Define a valid key event.
1585 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001586 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001587 AMETA_NONE, currentTime);
1588
1589 return args;
1590}
1591
Prabir Pradhan678438e2023-04-13 19:32:51 +00001592[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1593 int32_t displayId,
1594 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001595 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001596 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1597 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1598 }
1599
chaviwd1c23182019-12-20 18:44:56 -08001600 PointerProperties pointerProperties[pointerCount];
1601 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001602
chaviwd1c23182019-12-20 18:44:56 -08001603 for (size_t i = 0; i < pointerCount; i++) {
1604 pointerProperties[i].clear();
1605 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001606 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001607
chaviwd1c23182019-12-20 18:44:56 -08001608 pointerCoords[i].clear();
1609 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1610 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1611 }
Jackal Guof9696682018-10-05 12:23:23 +08001612
1613 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1614 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001615 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001616 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1617 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001618 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001619 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001620 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001621 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001622
1623 return args;
1624}
1625
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001626static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1627 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1628}
1629
chaviwd1c23182019-12-20 18:44:56 -08001630static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1631 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1632}
1633
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001634static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1635 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001636 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001637}
1638
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001639} // namespace
1640
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001641/**
1642 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1643 * broken channel.
1644 */
1645TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1647 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001648 sp<FakeWindowHandle>::make(application, mDispatcher,
1649 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001650
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001651 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001652
1653 // Window closes its channel, but the window remains.
1654 window->destroyReceiver();
1655 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1656}
1657
Arthur Hungb92218b2018-08-14 12:00:21 +08001658TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1661 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001662
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001667
1668 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001669 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001670}
1671
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001672TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1675 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001678 // Inject a MotionEvent to an unknown display.
1679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1682
1683 // Window should receive motion event.
1684 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1685}
1686
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 * Calling onWindowInfosChanged once should not cause any issues.
1689 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 * called twice.
1691 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001692TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001694 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1695 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703
1704 // Window should receive motion event.
1705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1706}
1707
1708/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710 */
1711TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1714 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723
1724 // Window should receive motion event.
1725 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1726}
1727
Arthur Hungb92218b2018-08-14 12:00:21 +08001728// The foreground window should receive the first touch down event.
1729TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001731 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001733 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001734 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001735
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001736 mDispatcher->onWindowInfosChanged(
1737 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001741
1742 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001743 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001744 windowSecond->assertNoEvents();
1745}
1746
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001747/**
1748 * Two windows: A top window, and a wallpaper behind the window.
1749 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1750 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001751 * 1. foregroundWindow <-- dup touch to wallpaper
1752 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001753 */
1754TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1756 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001757 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001758 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001759 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001760 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001761 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001762
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001763 mDispatcher->onWindowInfosChanged(
1764 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001767 {100, 200}))
1768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1769
1770 // Both foreground window and its wallpaper should receive the touch down
1771 foregroundWindow->consumeMotionDown();
1772 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1773
1774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001775 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 ADISPLAY_ID_DEFAULT, {110, 200}))
1777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1778
1779 foregroundWindow->consumeMotionMove();
1780 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1781
1782 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001783 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784 foregroundWindow->consumeMotionCancel();
1785 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1786 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1787}
1788
1789/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001790 * Two fingers down on the window, and lift off the first finger.
1791 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1792 * contains a single pointer.
1793 */
1794TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1796 sp<FakeWindowHandle> window =
1797 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1798
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1802 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1803 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001804 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001805 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1806 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1807 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1808 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001809 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001810 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1811 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1812 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1813 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001814 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1815 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1816 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1817
1818 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001819 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001820 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1821 window->consumeMotionEvent(
1822 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1823}
1824
1825/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1827 * with the following differences:
1828 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1829 * clean up the connection.
1830 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1831 * Ensure that there's no crash in the dispatcher.
1832 */
1833TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1835 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001837 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001838 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001839 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001840 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged(
1843 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001846 {100, 200}))
1847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1848
1849 // Both foreground window and its wallpaper should receive the touch down
1850 foregroundWindow->consumeMotionDown();
1851 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1852
1853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001854 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001855 ADISPLAY_ID_DEFAULT, {110, 200}))
1856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1857
1858 foregroundWindow->consumeMotionMove();
1859 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1860
1861 // Wallpaper closes its channel, but the window remains.
1862 wallpaperWindow->destroyReceiver();
1863 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1864
1865 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1866 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001867 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001868 foregroundWindow->consumeMotionCancel();
1869}
1870
Arthur Hungc539dbb2022-12-08 07:45:36 +00001871class ShouldSplitTouchFixture : public InputDispatcherTest,
1872 public ::testing::WithParamInterface<bool> {};
1873INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1874 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001875/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 * A single window that receives touch (on top), and a wallpaper window underneath it.
1877 * The top window gets a multitouch gesture.
1878 * Ensure that wallpaper gets the same gesture.
1879 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001880TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001882 sp<FakeWindowHandle> foregroundWindow =
1883 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1884 foregroundWindow->setDupTouchToWallpaper(true);
1885 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001886
1887 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001888 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001889 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001891 mDispatcher->onWindowInfosChanged(
1892 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893
1894 // Touch down on top window
1895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001896 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 {100, 100}))
1898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1899
1900 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001901 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1903
1904 // Second finger down on the top window
1905 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001906 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001908 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1909 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910 .build();
1911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001912 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 InputEventInjectionSync::WAIT_FOR_RESULT))
1914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915
Harry Cutts33476232023-01-30 19:57:29 +00001916 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1917 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919
1920 const MotionEvent secondFingerUpEvent =
1921 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1922 .displayId(ADISPLAY_ID_DEFAULT)
1923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001924 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1925 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926 .build();
1927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001928 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001929 InputEventInjectionSync::WAIT_FOR_RESULT))
1930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1931 foregroundWindow->consumeMotionPointerUp(0);
1932 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1933
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001936 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1937 AINPUT_SOURCE_TOUCHSCREEN)
1938 .displayId(ADISPLAY_ID_DEFAULT)
1939 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001941 .x(100)
1942 .y(100))
1943 .build(),
1944 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1946 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1947 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948}
1949
1950/**
1951 * Two windows: a window on the left and window on the right.
1952 * A third window, wallpaper, is behind both windows, and spans both top windows.
1953 * The first touch down goes to the left window. A second pointer touches down on the right window.
1954 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1955 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1956 * ACTION_POINTER_DOWN(1).
1957 */
1958TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1960 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001961 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001963 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964
1965 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001966 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001968 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969
1970 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001971 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001973 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001975 mDispatcher->onWindowInfosChanged(
1976 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1977 {},
1978 0,
1979 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980
1981 // Touch down on left window
1982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001983 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 {100, 100}))
1985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1986
1987 // Both foreground window and its wallpaper should receive the touch down
1988 leftWindow->consumeMotionDown();
1989 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1990
1991 // Second finger down on the right window
1992 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001993 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001994 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001995 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1996 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997 .build();
1998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001999 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 InputEventInjectionSync::WAIT_FOR_RESULT))
2001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2002
2003 leftWindow->consumeMotionMove();
2004 // Since the touch is split, right window gets ACTION_DOWN
2005 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002006 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 expectedWallpaperFlags);
2008
2009 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002010 mDispatcher->onWindowInfosChanged(
2011 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 leftWindow->consumeMotionCancel();
2013 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2014 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2015
2016 // The pointer that's still down on the right window moves, and goes to the right window only.
2017 // As far as the dispatcher's concerned though, both pointers are still present.
2018 const MotionEvent secondFingerMoveEvent =
2019 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2020 .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(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 .build();
2024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002025 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 InputEventInjectionSync::WAIT_FOR_RESULT));
2027 rightWindow->consumeMotionMove();
2028
2029 leftWindow->assertNoEvents();
2030 rightWindow->assertNoEvents();
2031 wallpaperWindow->assertNoEvents();
2032}
2033
Arthur Hungc539dbb2022-12-08 07:45:36 +00002034/**
2035 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2036 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2037 * The right window should receive ACTION_DOWN.
2038 */
2039TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041 sp<FakeWindowHandle> leftWindow =
2042 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2043 leftWindow->setFrame(Rect(0, 0, 200, 200));
2044 leftWindow->setDupTouchToWallpaper(true);
2045 leftWindow->setSlippery(true);
2046
2047 sp<FakeWindowHandle> rightWindow =
2048 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2049 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002050
2051 sp<FakeWindowHandle> wallpaperWindow =
2052 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2053 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002054
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002055 mDispatcher->onWindowInfosChanged(
2056 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2057 {},
2058 0,
2059 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002060
Arthur Hungc539dbb2022-12-08 07:45:36 +00002061 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066
2067 // Both foreground window and its wallpaper should receive the touch down
2068 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002069 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2070
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002073 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002074 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2076
Arthur Hungc539dbb2022-12-08 07:45:36 +00002077 leftWindow->consumeMotionCancel();
2078 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2079 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002080}
2081
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002082/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002083 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2084 * interactive, it might stop sending this flag.
2085 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2086 * to have a consistent input stream.
2087 *
2088 * Test procedure:
2089 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2090 * DOWN (new gesture).
2091 *
2092 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2093 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2094 *
2095 * We technically just need a single window here, but we are using two windows (spy on top and a
2096 * regular window below) to emulate the actual situation where it happens on the device.
2097 */
2098TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2100 sp<FakeWindowHandle> spyWindow =
2101 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2102 spyWindow->setFrame(Rect(0, 0, 200, 200));
2103 spyWindow->setTrustedOverlay(true);
2104 spyWindow->setSpy(true);
2105
2106 sp<FakeWindowHandle> window =
2107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2108 window->setFrame(Rect(0, 0, 200, 200));
2109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002110 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002111 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002112
2113 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002114 mDispatcher->notifyMotion(
2115 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2116 .deviceId(touchDeviceId)
2117 .policyFlags(DEFAULT_POLICY_FLAGS)
2118 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2119 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002120
Prabir Pradhan678438e2023-04-13 19:32:51 +00002121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2122 .deviceId(touchDeviceId)
2123 .policyFlags(DEFAULT_POLICY_FLAGS)
2124 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2125 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2126 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2128 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2129 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2130 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2131
2132 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002133 mDispatcher->notifyMotion(
2134 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2135 .deviceId(touchDeviceId)
2136 .policyFlags(0)
2137 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2138 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2139 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002140 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2141 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2142
2143 // We don't need to reset the device to reproduce the issue, but the reset event typically
2144 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002145 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002146
2147 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002148 mDispatcher->notifyMotion(
2149 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2150 .deviceId(touchDeviceId)
2151 .policyFlags(DEFAULT_POLICY_FLAGS)
2152 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2153 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002154 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2155 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2156
2157 // No more events
2158 spyWindow->assertNoEvents();
2159 window->assertNoEvents();
2160}
2161
2162/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002163 * Two windows: a window on the left and a window on the right.
2164 * Mouse is hovered from the right window into the left window.
2165 * Next, we tap on the left window, where the cursor was last seen.
2166 * The second tap is done onto the right window.
2167 * The mouse and tap are from two different devices.
2168 * We technically don't need to set the downtime / eventtime for these events, but setting these
2169 * explicitly helps during debugging.
2170 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2171 * In the buggy implementation, a tap on the right window would cause a crash.
2172 */
2173TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2175 sp<FakeWindowHandle> leftWindow =
2176 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2177 leftWindow->setFrame(Rect(0, 0, 200, 200));
2178
2179 sp<FakeWindowHandle> rightWindow =
2180 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2181 rightWindow->setFrame(Rect(200, 0, 400, 200));
2182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002183 mDispatcher->onWindowInfosChanged(
2184 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2186 // stale.
2187 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2188 const int32_t mouseDeviceId = 6;
2189 const int32_t touchDeviceId = 4;
2190 // Move the cursor from right
2191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002192 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002193 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2194 AINPUT_SOURCE_MOUSE)
2195 .deviceId(mouseDeviceId)
2196 .downTime(baseTime + 10)
2197 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002198 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002199 .build()));
2200 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2201
2202 // .. to the left window
2203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002204 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002205 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2206 AINPUT_SOURCE_MOUSE)
2207 .deviceId(mouseDeviceId)
2208 .downTime(baseTime + 10)
2209 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002210 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002211 .build()));
2212 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2213 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2214 // Now tap the left window
2215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002216 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002217 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2218 AINPUT_SOURCE_TOUCHSCREEN)
2219 .deviceId(touchDeviceId)
2220 .downTime(baseTime + 40)
2221 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002222 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002223 .build()));
2224 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2225 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2226
2227 // release tap
2228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002229 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002230 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2231 AINPUT_SOURCE_TOUCHSCREEN)
2232 .deviceId(touchDeviceId)
2233 .downTime(baseTime + 40)
2234 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002235 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002236 .build()));
2237 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2238
2239 // Tap the window on the right
2240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002241 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2243 AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .downTime(baseTime + 60)
2246 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002247 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 .build()));
2249 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2250
2251 // release tap
2252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002254 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2255 AINPUT_SOURCE_TOUCHSCREEN)
2256 .deviceId(touchDeviceId)
2257 .downTime(baseTime + 60)
2258 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002259 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002260 .build()));
2261 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2262
2263 // No more events
2264 leftWindow->assertNoEvents();
2265 rightWindow->assertNoEvents();
2266}
2267
2268/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002269 * Start hovering in a window. While this hover is still active, make another window appear on top.
2270 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2271 * While the top window is present, the hovering is stopped.
2272 * Later, hovering gets resumed again.
2273 * Ensure that new hover gesture is handled correctly.
2274 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2275 * to the window that's currently being hovered over.
2276 */
2277TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2279 sp<FakeWindowHandle> window =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2281 window->setFrame(Rect(0, 0, 200, 200));
2282
2283 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002285
2286 // Start hovering in the window
2287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2288 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2289 .build());
2290 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2291
2292 // Now, an obscuring window appears!
2293 sp<FakeWindowHandle> obscuringWindow =
2294 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2295 ADISPLAY_ID_DEFAULT,
2296 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2297 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2298 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2299 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2300 obscuringWindow->setNoInputChannel(true);
2301 obscuringWindow->setFocusable(false);
2302 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002303 mDispatcher->onWindowInfosChanged(
2304 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002305
2306 // While this new obscuring window is present, the hovering is stopped
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2309 .build());
2310 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2311
2312 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002313 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002314
2315 // And a new hover gesture starts.
2316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2317 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2318 .build());
2319 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2320}
2321
2322/**
2323 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2324 * the obscuring window.
2325 */
2326TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2328 sp<FakeWindowHandle> window =
2329 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2330 window->setFrame(Rect(0, 0, 200, 200));
2331
2332 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002333 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002334
2335 // Start hovering in the window
2336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2337 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2338 .build());
2339 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2340
2341 // Now, an obscuring window appears!
2342 sp<FakeWindowHandle> obscuringWindow =
2343 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2344 ADISPLAY_ID_DEFAULT,
2345 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2346 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2347 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2348 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2349 obscuringWindow->setNoInputChannel(true);
2350 obscuringWindow->setFocusable(false);
2351 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002352 mDispatcher->onWindowInfosChanged(
2353 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002354
2355 // While this new obscuring window is present, the hovering continues. The event can't go to the
2356 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2357 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2358 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2359 .build());
2360 obscuringWindow->assertNoEvents();
2361 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2362
2363 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002365
2366 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2367 // so it should generate a HOVER_ENTER
2368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2370 .build());
2371 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2372
2373 // Now the MOVE should be getting dispatched normally
2374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2376 .build());
2377 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2378}
2379
2380/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002381 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2382 * events are delivered to the window.
2383 */
2384TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2386 sp<FakeWindowHandle> window =
2387 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2388 window->setFrame(Rect(0, 0, 200, 200));
2389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2390
2391 // Start hovering in the window
2392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2393 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2394 .build());
2395 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2396
2397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2398 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2399 .build());
2400 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2401
2402 // Scroll with the mouse
2403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2405 .build());
2406 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2407}
2408
2409using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2410
2411/**
2412 * One window. Stylus down on the window. Next, touch from another device goes down.
2413 */
2414TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2416 sp<FakeWindowHandle> window =
2417 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2418 window->setFrame(Rect(0, 0, 200, 200));
2419
2420 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2421
2422 constexpr int32_t touchDeviceId = 4;
2423 constexpr int32_t stylusDeviceId = 2;
2424
2425 // Stylus down
2426 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2427 .deviceId(stylusDeviceId)
2428 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2429 .build());
2430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2431
2432 // Touch down
2433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2434 .deviceId(touchDeviceId)
2435 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2436 .build());
2437 // Touch cancels stylus
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2439 WithCoords(100, 110)));
2440 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2441 WithCoords(140, 145)));
2442
2443 // Touch move
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2445 .deviceId(touchDeviceId)
2446 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2447 .build());
2448 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2449 WithCoords(141, 146)));
2450
2451 // Subsequent stylus movements are dropped
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2453 .deviceId(stylusDeviceId)
2454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2455 .build());
2456 window->assertNoEvents();
2457}
2458
2459/**
2460 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2461 * down.
2462 * Similar test as above, but with added SPY window.
2463 */
2464TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2466 sp<FakeWindowHandle> window =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2468 sp<FakeWindowHandle> spyWindow =
2469 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2470 spyWindow->setFrame(Rect(0, 0, 200, 200));
2471 spyWindow->setTrustedOverlay(true);
2472 spyWindow->setSpy(true);
2473 window->setFrame(Rect(0, 0, 200, 200));
2474
2475 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2476
2477 constexpr int32_t touchDeviceId = 4;
2478 constexpr int32_t stylusDeviceId = 2;
2479
2480 // Stylus down
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486 spyWindow->consumeMotionEvent(
2487 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2488
2489 // Touch down
2490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2491 .deviceId(touchDeviceId)
2492 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2493 .build());
2494
2495 // Touch move
2496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2497 .deviceId(touchDeviceId)
2498 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2499 .build());
2500 window->consumeMotionEvent(
2501 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2502 spyWindow->consumeMotionEvent(
2503 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2504 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2505 spyWindow->consumeMotionEvent(
2506 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2507 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2508 spyWindow->consumeMotionEvent(
2509 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2510 // Subsequent stylus movements are dropped
2511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2512 .deviceId(stylusDeviceId)
2513 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2514 .build());
2515
2516 window->assertNoEvents();
2517 spyWindow->assertNoEvents();
2518}
2519
2520/**
2521 * One window. Stylus hover on the window. Next, touch from another device goes down.
2522 */
2523TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2525 sp<FakeWindowHandle> window =
2526 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2527 window->setFrame(Rect(0, 0, 200, 200));
2528
2529 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2530
2531 constexpr int32_t touchDeviceId = 4;
2532 constexpr int32_t stylusDeviceId = 2;
2533
2534 // Stylus down on the window
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2536 .deviceId(stylusDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2538 .build());
2539 window->consumeMotionEvent(
2540 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2541
2542 // Touch down on window
2543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2544 .deviceId(touchDeviceId)
2545 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2546 .build());
2547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2548 .deviceId(touchDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2550 .build());
2551 window->consumeMotionEvent(
2552 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2554 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2555 // Subsequent stylus movements are ignored
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2557 .deviceId(stylusDeviceId)
2558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2559 .build());
2560 window->assertNoEvents();
2561}
2562
2563/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002564 * Two windows: a window on the left and a window on the right.
2565 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2566 * down. Then, on the left window, also place second touch pointer down.
2567 * This test tries to reproduce a crash.
2568 * In the buggy implementation, second pointer down on the left window would cause a crash.
2569 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002570TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> leftWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2574 leftWindow->setFrame(Rect(0, 0, 200, 200));
2575
2576 sp<FakeWindowHandle> rightWindow =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2578 rightWindow->setFrame(Rect(200, 0, 400, 200));
2579
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002580 mDispatcher->onWindowInfosChanged(
2581 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002582
2583 const int32_t touchDeviceId = 4;
2584 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002585
2586 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2588 .deviceId(mouseDeviceId)
2589 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2590 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002591 leftWindow->consumeMotionEvent(
2592 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2593
2594 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002595 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2596 .deviceId(mouseDeviceId)
2597 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2598 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2599 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002600
2601 leftWindow->consumeMotionEvent(
2602 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2603 leftWindow->consumeMotionEvent(
2604 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2605
Prabir Pradhan678438e2023-04-13 19:32:51 +00002606 mDispatcher->notifyMotion(
2607 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2608 .deviceId(mouseDeviceId)
2609 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2610 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2611 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2612 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002613 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2614
2615 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2617 .deviceId(touchDeviceId)
2618 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2619 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002620 leftWindow->consumeMotionEvent(
2621 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002622 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2623
2624 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002625 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
2627 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2628 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2629 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002630 leftWindow->consumeMotionEvent(
2631 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2632 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2633 // current implementation.
2634 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2635 rightWindow->consumeMotionEvent(
2636 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2637
2638 leftWindow->assertNoEvents();
2639 rightWindow->assertNoEvents();
2640}
2641
2642/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002643 * Two windows: a window on the left and a window on the right.
2644 * Mouse is hovered on the left window and stylus is hovered on the right window.
2645 */
2646TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> leftWindow =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2650 leftWindow->setFrame(Rect(0, 0, 200, 200));
2651
2652 sp<FakeWindowHandle> rightWindow =
2653 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2654 rightWindow->setFrame(Rect(200, 0, 400, 200));
2655
2656 mDispatcher->onWindowInfosChanged(
2657 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2658
2659 const int32_t stylusDeviceId = 3;
2660 const int32_t mouseDeviceId = 6;
2661
2662 // Start hovering over the left window
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2664 .deviceId(mouseDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2666 .build());
2667 leftWindow->consumeMotionEvent(
2668 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2669
2670 // Stylus hovered on right window
2671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2672 .deviceId(stylusDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2674 .build());
2675 leftWindow->consumeMotionEvent(
2676 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2677 rightWindow->consumeMotionEvent(
2678 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2679
2680 // Subsequent HOVER_MOVE events are dispatched correctly.
2681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2682 .deviceId(mouseDeviceId)
2683 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2684 .build());
2685 leftWindow->consumeMotionEvent(
2686 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2687 rightWindow->consumeMotionEvent(
2688 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2689
2690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2691 .deviceId(stylusDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2693 .build());
2694 leftWindow->consumeMotionEvent(
2695 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2696 rightWindow->consumeMotionEvent(
2697 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2698
2699 leftWindow->assertNoEvents();
2700 rightWindow->assertNoEvents();
2701}
2702
2703/**
2704 * Three windows: a window on the left and a window on the right.
2705 * And a spy window that's positioned above all of them.
2706 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2707 * Check the stream that's received by the spy.
2708 */
2709TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2711
2712 sp<FakeWindowHandle> spyWindow =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2714 spyWindow->setFrame(Rect(0, 0, 400, 400));
2715 spyWindow->setTrustedOverlay(true);
2716 spyWindow->setSpy(true);
2717
2718 sp<FakeWindowHandle> leftWindow =
2719 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2720 leftWindow->setFrame(Rect(0, 0, 200, 200));
2721
2722 sp<FakeWindowHandle> rightWindow =
2723 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2724
2725 rightWindow->setFrame(Rect(200, 0, 400, 200));
2726
2727 mDispatcher->onWindowInfosChanged(
2728 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2729
2730 const int32_t stylusDeviceId = 1;
2731 const int32_t touchDeviceId = 2;
2732
2733 // Stylus down on the left window
2734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2735 .deviceId(stylusDeviceId)
2736 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2737 .build());
2738 leftWindow->consumeMotionEvent(
2739 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2740 spyWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2742
2743 // Touch down on the right window
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2745 .deviceId(touchDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2747 .build());
2748 leftWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2750 spyWindow->consumeMotionEvent(
2751 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2752 rightWindow->consumeMotionEvent(
2753 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2754 spyWindow->consumeMotionEvent(
2755 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2756
2757 // Stylus movements continue, but are ignored because the touch went down more recently.
2758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2759 .deviceId(stylusDeviceId)
2760 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2761 .build());
2762
2763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2764 .deviceId(touchDeviceId)
2765 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2766 .build());
2767 rightWindow->consumeMotionEvent(
2768 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2769 spyWindow->consumeMotionEvent(
2770 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2771
2772 spyWindow->assertNoEvents();
2773 leftWindow->assertNoEvents();
2774 rightWindow->assertNoEvents();
2775}
2776
2777/**
2778 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2779 * both.
2780 * Check hover in left window and touch down in the right window.
2781 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2782 */
2783TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2785
2786 sp<FakeWindowHandle> spyWindow =
2787 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2788 spyWindow->setFrame(Rect(0, 0, 400, 400));
2789 spyWindow->setTrustedOverlay(true);
2790 spyWindow->setSpy(true);
2791
2792 sp<FakeWindowHandle> leftWindow =
2793 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2794 leftWindow->setFrame(Rect(0, 0, 200, 200));
2795
2796 sp<FakeWindowHandle> rightWindow =
2797 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2798 rightWindow->setFrame(Rect(200, 0, 400, 200));
2799
2800 mDispatcher->onWindowInfosChanged(
2801 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2802
2803 const int32_t stylusDeviceId = 1;
2804 const int32_t touchDeviceId = 2;
2805
2806 // Stylus hover on the left window
2807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2808 .deviceId(stylusDeviceId)
2809 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2810 .build());
2811 leftWindow->consumeMotionEvent(
2812 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2813 spyWindow->consumeMotionEvent(
2814 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2815
2816 // Touch down on the right window.
2817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2818 .deviceId(touchDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2820 .build());
2821 leftWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2823 spyWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2825 spyWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2827 rightWindow->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2829
2830 // Stylus movements continue, but are ignored because the touch is down.
2831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2832 .deviceId(stylusDeviceId)
2833 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2834 .build());
2835
2836 // Touch movements continue. They should be delivered to the right window and to the spy
2837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2838 .deviceId(touchDeviceId)
2839 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2840 .build());
2841 spyWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2843 rightWindow->consumeMotionEvent(
2844 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2845
2846 spyWindow->assertNoEvents();
2847 leftWindow->assertNoEvents();
2848 rightWindow->assertNoEvents();
2849}
2850
2851/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 * On a single window, use two different devices: mouse and touch.
2853 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2854 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2855 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2856 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2857 * represent a new gesture.
2858 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002859TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2861 sp<FakeWindowHandle> window =
2862 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2863 window->setFrame(Rect(0, 0, 400, 400));
2864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002866
2867 const int32_t touchDeviceId = 4;
2868 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002869
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002870 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2874 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002875 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2879 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2880 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002881 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2883 .deviceId(touchDeviceId)
2884 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2885 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2886 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002887 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2888 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2889 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2890
2891 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2893 .deviceId(mouseDeviceId)
2894 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2895 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002897
2898 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002899 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002900 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2901
Prabir Pradhan678438e2023-04-13 19:32:51 +00002902 mDispatcher->notifyMotion(
2903 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2904 .deviceId(mouseDeviceId)
2905 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2906 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2908 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002909 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2910
2911 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002912 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2913 .deviceId(touchDeviceId)
2914 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2915 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2916 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002917 // Since we already canceled this touch gesture, it will be ignored until a completely new
2918 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2919 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2920 // However, mouse movements should continue to work.
2921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2922 .deviceId(mouseDeviceId)
2923 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2924 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2925 .build());
2926 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2927
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002928 window->assertNoEvents();
2929}
2930
2931/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002932 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2933 * the injected event.
2934 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2937 sp<FakeWindowHandle> window =
2938 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2939 window->setFrame(Rect(0, 0, 400, 400));
2940
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002942
2943 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002944 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2945 // completion.
2946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002947 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002948 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2949 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002951 .build()));
2952 window->consumeMotionEvent(
2953 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2954
2955 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2956 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2958 .deviceId(touchDeviceId)
2959 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2960 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002961
2962 window->consumeMotionEvent(
2963 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2964 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2965}
2966
2967/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002968 * This test is similar to the test above, but the sequence of injected events is different.
2969 *
2970 * Two windows: a window on the left and a window on the right.
2971 * Mouse is hovered over the left window.
2972 * Next, we tap on the left window, where the cursor was last seen.
2973 *
2974 * After that, we inject one finger down onto the right window, and then a second finger down onto
2975 * the left window.
2976 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2977 * window (first), and then another on the left window (second).
2978 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2979 * In the buggy implementation, second finger down on the left window would cause a crash.
2980 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002981TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2983 sp<FakeWindowHandle> leftWindow =
2984 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2985 leftWindow->setFrame(Rect(0, 0, 200, 200));
2986
2987 sp<FakeWindowHandle> rightWindow =
2988 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2989 rightWindow->setFrame(Rect(200, 0, 400, 200));
2990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002991 mDispatcher->onWindowInfosChanged(
2992 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002993
2994 const int32_t mouseDeviceId = 6;
2995 const int32_t touchDeviceId = 4;
2996 // Hover over the left window. Keep the cursor there.
2997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002998 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002999 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3000 AINPUT_SOURCE_MOUSE)
3001 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003003 .build()));
3004 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3005
3006 // Tap on left window
3007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003008 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003009 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3010 AINPUT_SOURCE_TOUCHSCREEN)
3011 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003012 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003013 .build()));
3014
3015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003016 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003017 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3018 AINPUT_SOURCE_TOUCHSCREEN)
3019 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003020 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003021 .build()));
3022 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3023 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3024 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3025
3026 // First finger down on right window
3027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003028 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003029 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3030 AINPUT_SOURCE_TOUCHSCREEN)
3031 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003032 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003033 .build()));
3034 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3035
3036 // Second finger down on the left window
3037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003038 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003039 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3040 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003041 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3042 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003043 .build()));
3044 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3045 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3046
3047 // No more events
3048 leftWindow->assertNoEvents();
3049 rightWindow->assertNoEvents();
3050}
3051
3052/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003053 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3054 * While the touch is down, new hover events from the stylus device should be ignored. After the
3055 * touch is gone, stylus hovering should start working again.
3056 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003057TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3059 sp<FakeWindowHandle> window =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3061 window->setFrame(Rect(0, 0, 200, 200));
3062
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003063 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003064
3065 const int32_t stylusDeviceId = 5;
3066 const int32_t touchDeviceId = 4;
3067 // Start hovering with stylus
3068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003069 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003071 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003072 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003073 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003075
3076 // Finger down on the window
3077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003078 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003080 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003081 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003082 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003083 window->consumeMotionEvent(
3084 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3085 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003086
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003087 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003088 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003089 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003090 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3091 AINPUT_SOURCE_STYLUS)
3092 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003093 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003094 .build()));
3095 // No event should be sent. This event should be ignored because a pointer from another device
3096 // is already down.
3097
3098 // Lift up the finger
3099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003100 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003101 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3102 AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003105 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003106 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003107
3108 // Now that the touch is gone, stylus hovering should start working again
3109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003110 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003111 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3112 AINPUT_SOURCE_STYLUS)
3113 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003114 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003115 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003116 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3117 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003118 window->assertNoEvents();
3119}
3120
3121/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122 * A spy window above a window with no input channel.
3123 * Start hovering with a stylus device, and then tap with it.
3124 * Ensure spy window receives the entire sequence.
3125 */
3126TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3128 sp<FakeWindowHandle> spyWindow =
3129 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3130 spyWindow->setFrame(Rect(0, 0, 200, 200));
3131 spyWindow->setTrustedOverlay(true);
3132 spyWindow->setSpy(true);
3133 sp<FakeWindowHandle> window =
3134 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3135 window->setNoInputChannel(true);
3136 window->setFrame(Rect(0, 0, 200, 200));
3137
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003138 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3142 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3143 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003144 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3145 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3147 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3148 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3150
3151 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3153 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3154 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3156
3157 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3160 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003161 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3162
3163 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003164 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3165 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3166 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003167 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3168 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003169 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3171 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003172 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3173
3174 // No more events
3175 spyWindow->assertNoEvents();
3176 window->assertNoEvents();
3177}
3178
3179/**
3180 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3181 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3182 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3183 * While the mouse is down, new move events from the touch device should be ignored.
3184 */
3185TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3187 sp<FakeWindowHandle> spyWindow =
3188 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3189 spyWindow->setFrame(Rect(0, 0, 200, 200));
3190 spyWindow->setTrustedOverlay(true);
3191 spyWindow->setSpy(true);
3192 sp<FakeWindowHandle> window =
3193 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3194 window->setFrame(Rect(0, 0, 200, 200));
3195
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003196 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197
3198 const int32_t mouseDeviceId = 7;
3199 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003200
3201 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003202 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3203 .deviceId(mouseDeviceId)
3204 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3205 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003206 spyWindow->consumeMotionEvent(
3207 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3208 window->consumeMotionEvent(
3209 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3210
3211 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3213 .deviceId(touchDeviceId)
3214 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3215 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003216 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3218 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3219 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3220
Prabir Pradhan678438e2023-04-13 19:32:51 +00003221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3222 .deviceId(touchDeviceId)
3223 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3224 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003225 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3226 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3227
3228 // Pilfer the stream
3229 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3230 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3231
Prabir Pradhan678438e2023-04-13 19:32:51 +00003232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3233 .deviceId(touchDeviceId)
3234 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3235 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003236 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3237
3238 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
3241 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3243 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003244
3245 spyWindow->consumeMotionEvent(
3246 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3247 spyWindow->consumeMotionEvent(
3248 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3249 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3250
Prabir Pradhan678438e2023-04-13 19:32:51 +00003251 mDispatcher->notifyMotion(
3252 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3253 .deviceId(mouseDeviceId)
3254 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3255 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3257 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003258 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3259 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3260
3261 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003262 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3263 .deviceId(mouseDeviceId)
3264 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3265 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3266 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003267 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3268 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3269
3270 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3272 .deviceId(touchDeviceId)
3273 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3274 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003275
3276 // No more events
3277 spyWindow->assertNoEvents();
3278 window->assertNoEvents();
3279}
3280
3281/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003282 * On the display, have a single window, and also an area where there's no window.
3283 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3284 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3285 */
3286TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3288 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003289 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003292
3293 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003295
3296 mDispatcher->waitForIdle();
3297 window->assertNoEvents();
3298
3299 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003300 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003301 mDispatcher->waitForIdle();
3302 window->consumeMotionDown();
3303}
3304
3305/**
3306 * Same test as above, but instead of touching the empty space, the first touch goes to
3307 * non-touchable window.
3308 */
3309TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3311 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003312 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003313 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3314 window1->setTouchable(false);
3315 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003316 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003317 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3318
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003319 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003320
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003321 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003322 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003323
3324 mDispatcher->waitForIdle();
3325 window1->assertNoEvents();
3326 window2->assertNoEvents();
3327
3328 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003329 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003330 mDispatcher->waitForIdle();
3331 window2->consumeMotionDown();
3332}
3333
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003334/**
3335 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3336 * to the event time of the first ACTION_DOWN sent to the particular window.
3337 */
3338TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3339 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3340 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003341 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003342 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3343 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003344 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003345 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3346
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003347 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003348
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003349 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003350 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003351
3352 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353
3354 MotionEvent* motionEvent1 = window1->consumeMotion();
3355 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003356 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3358 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003359
3360 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003361 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003362 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003363 MotionEvent* motionEvent2 = window2->consumeMotion();
3364 ASSERT_NE(motionEvent2, nullptr);
3365 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003366 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003368
3369 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003370 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003371 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003372 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003373
3374 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003375 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003376 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003377 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003378
3379 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3380 window1->consumeMotionMove();
3381 window1->assertNoEvents();
3382
3383 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003384 mDispatcher->notifyMotion(
3385 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003386 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003387 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003388
Prabir Pradhan678438e2023-04-13 19:32:51 +00003389 mDispatcher->notifyMotion(
3390 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003391 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003392 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003393}
3394
Garfield Tandf26e862020-07-01 20:18:19 -07003395TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003397 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003398 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003399 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003400 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003401 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003402 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003403
3404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3405
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003406 mDispatcher->onWindowInfosChanged(
3407 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003408
3409 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003411 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003412 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3413 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003414 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003415 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003416 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003417
3418 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003420 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003421 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3422 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003424 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003425 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3426 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003427
3428 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003431 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3432 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003433 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003434 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003435 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3436 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003437
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003439 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003440 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3441 AINPUT_SOURCE_MOUSE)
3442 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3443 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003444 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003445 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003446 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003449 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003450 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3451 AINPUT_SOURCE_MOUSE)
3452 .buttonState(0)
3453 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003454 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003455 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003456 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003457
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003459 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003460 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3461 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003463 .build()));
3464 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3465
3466 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003468 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003469 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3470 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003472 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003473 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003474
3475 // No more events
3476 windowLeft->assertNoEvents();
3477 windowRight->assertNoEvents();
3478}
3479
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003480/**
3481 * Put two fingers down (and don't release them) and click the mouse button.
3482 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3483 * currently active gesture should be canceled, and the new one should proceed.
3484 */
3485TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3487 sp<FakeWindowHandle> window =
3488 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3489 window->setFrame(Rect(0, 0, 600, 800));
3490
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003492
3493 const int32_t touchDeviceId = 4;
3494 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003495
3496 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3498 .deviceId(touchDeviceId)
3499 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003501
Prabir Pradhan678438e2023-04-13 19:32:51 +00003502 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3503 .deviceId(touchDeviceId)
3504 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3505 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3506 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003507 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3508 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3509
3510 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3512 .deviceId(mouseDeviceId)
3513 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3514 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003516 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3517 WithPointerCount(2u)));
3518 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3519
Prabir Pradhan678438e2023-04-13 19:32:51 +00003520 mDispatcher->notifyMotion(
3521 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3522 .deviceId(mouseDeviceId)
3523 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3524 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3528
3529 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3530 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3532 .deviceId(touchDeviceId)
3533 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3534 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3535 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003536 window->assertNoEvents();
3537}
3538
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003539TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3541
3542 sp<FakeWindowHandle> spyWindow =
3543 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3544 spyWindow->setFrame(Rect(0, 0, 600, 800));
3545 spyWindow->setTrustedOverlay(true);
3546 spyWindow->setSpy(true);
3547 sp<FakeWindowHandle> window =
3548 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3549 window->setFrame(Rect(0, 0, 600, 800));
3550
3551 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003552 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003553
3554 // Send mouse cursor to the window
3555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003556 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003557 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3558 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003559 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003560 .build()));
3561
3562 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3563 WithSource(AINPUT_SOURCE_MOUSE)));
3564 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3565 WithSource(AINPUT_SOURCE_MOUSE)));
3566
3567 window->assertNoEvents();
3568 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003569}
3570
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003571TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3573
3574 sp<FakeWindowHandle> spyWindow =
3575 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3576 spyWindow->setFrame(Rect(0, 0, 600, 800));
3577 spyWindow->setTrustedOverlay(true);
3578 spyWindow->setSpy(true);
3579 sp<FakeWindowHandle> window =
3580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3581 window->setFrame(Rect(0, 0, 600, 800));
3582
3583 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003584 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003585
3586 // Send mouse cursor to the window
3587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003588 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003589 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3590 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003592 .build()));
3593
3594 // Move mouse cursor
3595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003596 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003597 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3598 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003599 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003600 .build()));
3601
3602 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3603 WithSource(AINPUT_SOURCE_MOUSE)));
3604 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3605 WithSource(AINPUT_SOURCE_MOUSE)));
3606 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3607 WithSource(AINPUT_SOURCE_MOUSE)));
3608 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3609 WithSource(AINPUT_SOURCE_MOUSE)));
3610 // Touch down on the window
3611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003612 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003613 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3614 AINPUT_SOURCE_TOUCHSCREEN)
3615 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003616 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003617 .build()));
3618 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3619 WithSource(AINPUT_SOURCE_MOUSE)));
3620 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3621 WithSource(AINPUT_SOURCE_MOUSE)));
3622 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3623 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3624 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3625 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3626
3627 // pilfer the motion, retaining the gesture on the spy window.
3628 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3629 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3630 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3631
3632 // Touch UP on the window
3633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003634 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003635 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3636 AINPUT_SOURCE_TOUCHSCREEN)
3637 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003638 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003639 .build()));
3640 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3641 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3642
3643 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3644 // to send a new gesture. It should again go to both windows (spy and the window below), just
3645 // like the first gesture did, before pilfering. The window configuration has not changed.
3646
3647 // One more tap - DOWN
3648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003649 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003650 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3651 AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003653 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003654 .build()));
3655 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3656 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3657 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3658 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3659
3660 // Touch UP on the window
3661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003662 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003663 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3664 AINPUT_SOURCE_TOUCHSCREEN)
3665 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003666 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003667 .build()));
3668 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3669 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3670 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3671 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3672
3673 window->assertNoEvents();
3674 spyWindow->assertNoEvents();
3675}
3676
Garfield Tandf26e862020-07-01 20:18:19 -07003677// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3678// directly in this test.
3679TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003681 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003682 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003683 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003684
3685 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003688
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003690 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003691 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3692 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003693 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003694 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003695 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003696 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003698 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003699 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3700 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003701 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003702 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003703 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3704 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003705
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_BUTTON_PRESS,
3709 AINPUT_SOURCE_MOUSE)
3710 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3711 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003712 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003713 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003714 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003715
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003718 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3719 AINPUT_SOURCE_MOUSE)
3720 .buttonState(0)
3721 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003722 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003723 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003724 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003725
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003727 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003728 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3729 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003730 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003731 .build()));
3732 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3733
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003734 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3735 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003737 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003738 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3739 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003740 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003741 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003742 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003743}
3744
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003745/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003746 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3747 * is generated.
3748 */
3749TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3751 sp<FakeWindowHandle> window =
3752 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3753 window->setFrame(Rect(0, 0, 1200, 800));
3754
3755 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003758
3759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003760 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003761 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3762 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003763 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003764 .build()));
3765 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3766
3767 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003768 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003769 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3770}
3771
3772/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003773 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3774 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003775TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3776 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3777 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3779 sp<FakeWindowHandle> window =
3780 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3781 window->setFrame(Rect(0, 0, 1200, 800));
3782
3783 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3784
3785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3786
3787 MotionEventBuilder hoverEnterBuilder =
3788 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3789 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3790 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3792 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3794 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3795 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3796 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3797}
3798
3799/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003800 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3801 */
3802TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3804 sp<FakeWindowHandle> window =
3805 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3806 window->setFrame(Rect(0, 0, 100, 100));
3807
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003808 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003809
3810 const int32_t mouseDeviceId = 7;
3811 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003812
3813 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3815 .deviceId(mouseDeviceId)
3816 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3817 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003818 window->consumeMotionEvent(
3819 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3820
3821 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3823 .deviceId(touchDeviceId)
3824 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3825 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003826
3827 window->consumeMotionEvent(
3828 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3829 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3830}
3831
3832/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003833 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003834 * The tap causes a HOVER_EXIT event to be generated because the current event
3835 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003836 */
3837TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3839 sp<FakeWindowHandle> window =
3840 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3841 window->setFrame(Rect(0, 0, 100, 100));
3842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3846 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003847 ASSERT_NO_FATAL_FAILURE(
3848 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3849 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003850
3851 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3853 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3854 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003855 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3857 WithSource(AINPUT_SOURCE_MOUSE))));
3858
3859 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003860 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3861 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3862
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3864 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3865 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003866 ASSERT_NO_FATAL_FAILURE(
3867 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3868 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3869}
3870
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003871TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3873 sp<FakeWindowHandle> windowDefaultDisplay =
3874 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3875 ADISPLAY_ID_DEFAULT);
3876 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3877 sp<FakeWindowHandle> windowSecondDisplay =
3878 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3879 SECOND_DISPLAY_ID);
3880 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3881
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003882 mDispatcher->onWindowInfosChanged(
3883 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003884
3885 // Set cursor position in window in default display and check that hover enter and move
3886 // events are generated.
3887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003889 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3890 AINPUT_SOURCE_MOUSE)
3891 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003892 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003893 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003894 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003895
3896 // Remove all windows in secondary display and check that no event happens on window in
3897 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003898 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3899
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003900 windowDefaultDisplay->assertNoEvents();
3901
3902 // Move cursor position in window in default display and check that only hover move
3903 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003904 mDispatcher->onWindowInfosChanged(
3905 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003908 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3909 AINPUT_SOURCE_MOUSE)
3910 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003912 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003913 windowDefaultDisplay->consumeMotionEvent(
3914 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3915 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003916 windowDefaultDisplay->assertNoEvents();
3917}
3918
Garfield Tan00f511d2019-06-12 16:55:40 -07003919TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003921
3922 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003923 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003924 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003925 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003926 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003927 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003928
3929 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3930
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003931 mDispatcher->onWindowInfosChanged(
3932 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003933
3934 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3935 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003937 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003938 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003939 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003940 windowRight->assertNoEvents();
3941}
3942
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003943TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003945 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3946 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003947 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003948
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003950 setFocusedWindow(window);
3951
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003952 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003953
Prabir Pradhan678438e2023-04-13 19:32:51 +00003954 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003955
3956 // Window should receive key down event.
3957 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3958
3959 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3960 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003961 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003962 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003963 AKEY_EVENT_FLAG_CANCELED);
3964}
3965
3966TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003968 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3969 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003970
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003971 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003972
Prabir Pradhan678438e2023-04-13 19:32:51 +00003973 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3974 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003975
3976 // Window should receive motion down event.
3977 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3978
3979 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3980 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003981 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003982 window->consumeMotionEvent(
3983 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003984}
3985
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003986TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3988 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3989 "Fake Window", ADISPLAY_ID_DEFAULT);
3990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003992
3993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3994 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3995 .build());
3996
3997 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3998
3999 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4000 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4001 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4002
4003 // After the device has been reset, a new hovering stream can be sent to the window
4004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4005 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4006 .build());
4007 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4008}
4009
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004010TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4013 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004014 window->setFocusable(true);
4015
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004016 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004017 setFocusedWindow(window);
4018
4019 window->consumeFocusEvent(true);
4020
Prabir Pradhan678438e2023-04-13 19:32:51 +00004021 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004022 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4023 const nsecs_t injectTime = keyArgs.eventTime;
4024 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004025 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004026 // The dispatching time should be always greater than or equal to intercept key timeout.
4027 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4028 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4029 std::chrono::nanoseconds(interceptKeyTimeout).count());
4030}
4031
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004032/**
4033 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4034 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004035TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004037 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4038 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004039 window->setFocusable(true);
4040
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004041 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004042 setFocusedWindow(window);
4043
4044 window->consumeFocusEvent(true);
4045
Prabir Pradhan678438e2023-04-13 19:32:51 +00004046 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004047 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004048
4049 // Set a value that's significantly larger than the default consumption timeout. If the
4050 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4051 mFakePolicy->setInterceptKeyTimeout(600ms);
4052 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4053 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004054 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4055}
4056
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004057/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004058 * Two windows. First is a regular window. Second does not overlap with the first, and has
4059 * WATCH_OUTSIDE_TOUCH.
4060 * Both windows are owned by the same UID.
4061 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4062 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4063 */
4064TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004066 sp<FakeWindowHandle> window =
4067 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004068 window->setFrame(Rect{0, 0, 100, 100});
4069
4070 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004071 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004072 ADISPLAY_ID_DEFAULT);
4073 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4074 outsideWindow->setWatchOutsideTouch(true);
4075 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004076 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004077
4078 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004079 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4080 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4081 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004082 window->consumeMotionDown();
4083 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4084 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4085 outsideWindow->consumeMotionEvent(
4086 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4087}
4088
4089/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004090 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4091 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4092 * ACTION_OUTSIDE event is sent per gesture.
4093 */
4094TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4095 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004097 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4098 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004099 window->setWatchOutsideTouch(true);
4100 window->setFrame(Rect{0, 0, 100, 100});
4101 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004102 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4103 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004104 secondWindow->setFrame(Rect{100, 100, 200, 200});
4105 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004106 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4107 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004108 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004109 mDispatcher->onWindowInfosChanged(
4110 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004111
4112 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4114 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4115 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004116 window->assertNoEvents();
4117 secondWindow->assertNoEvents();
4118
4119 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4120 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004121 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4122 ADISPLAY_ID_DEFAULT,
4123 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004124 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4125 window->consumeMotionEvent(
4126 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004127 secondWindow->consumeMotionDown();
4128 thirdWindow->assertNoEvents();
4129
4130 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4131 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004132 mDispatcher->notifyMotion(
4133 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4134 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004135 window->assertNoEvents();
4136 secondWindow->consumeMotionMove();
4137 thirdWindow->consumeMotionDown();
4138}
4139
Prabir Pradhan814fe082022-07-22 20:22:18 +00004140TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4143 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004144 window->setFocusable(true);
4145
Patrick Williamsd828f302023-04-28 17:52:08 -05004146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004147 setFocusedWindow(window);
4148
4149 window->consumeFocusEvent(true);
4150
Prabir Pradhan678438e2023-04-13 19:32:51 +00004151 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4152 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4153 mDispatcher->notifyKey(keyDown);
4154 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004155
4156 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4157 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4158
4159 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004160 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004161
4162 window->consumeFocusEvent(false);
4163
Prabir Pradhan678438e2023-04-13 19:32:51 +00004164 mDispatcher->notifyKey(keyDown);
4165 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004166 window->assertNoEvents();
4167}
4168
Arthur Hung96483742022-11-15 03:30:48 +00004169TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4171 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4172 "Fake Window", ADISPLAY_ID_DEFAULT);
4173 // Ensure window is non-split and have some transform.
4174 window->setPreventSplitting(true);
4175 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004177
4178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004179 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004180 {50, 50}))
4181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4182 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4183
4184 const MotionEvent secondFingerDownEvent =
4185 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4186 .displayId(ADISPLAY_ID_DEFAULT)
4187 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004188 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4189 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004190 .build();
4191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004192 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004193 InputEventInjectionSync::WAIT_FOR_RESULT))
4194 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4195
4196 const MotionEvent* event = window->consumeMotion();
4197 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4198 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4199 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4200 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4201 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4202}
4203
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004204/**
4205 * Two windows: a splittable and a non-splittable.
4206 * The non-splittable window shouldn't receive any "incomplete" gestures.
4207 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4208 * The second pointer should be dropped because the initial window is splittable, so it won't get
4209 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4210 * "incomplete" gestures.
4211 */
4212TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4214 sp<FakeWindowHandle> leftWindow =
4215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4216 ADISPLAY_ID_DEFAULT);
4217 leftWindow->setPreventSplitting(false);
4218 leftWindow->setFrame(Rect(0, 0, 100, 100));
4219 sp<FakeWindowHandle> rightWindow =
4220 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4221 ADISPLAY_ID_DEFAULT);
4222 rightWindow->setPreventSplitting(true);
4223 rightWindow->setFrame(Rect(100, 100, 200, 200));
4224 mDispatcher->onWindowInfosChanged(
4225 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4226
4227 // Touch down on left, splittable window
4228 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4229 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4230 .build());
4231 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4232
4233 mDispatcher->notifyMotion(
4234 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4235 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4236 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4237 .build());
4238 leftWindow->assertNoEvents();
4239 rightWindow->assertNoEvents();
4240}
4241
Harry Cuttsb166c002023-05-09 13:06:05 +00004242TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4243 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4244 sp<FakeWindowHandle> window =
4245 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4246 window->setFrame(Rect(0, 0, 400, 400));
4247 sp<FakeWindowHandle> trustedOverlay =
4248 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4249 ADISPLAY_ID_DEFAULT);
4250 trustedOverlay->setSpy(true);
4251 trustedOverlay->setTrustedOverlay(true);
4252
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004253 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004254
4255 // Start a three-finger touchpad swipe
4256 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4257 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4258 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4259 .build());
4260 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4261 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4262 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4263 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4264 .build());
4265 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4266 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4267 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4268 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4269 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4270 .build());
4271
4272 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4273 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4274 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4275
4276 // Move the swipe a bit
4277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4278 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4279 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4280 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4281 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4282 .build());
4283
4284 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4285
4286 // End the swipe
4287 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4288 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4289 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4290 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4291 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4292 .build());
4293 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4294 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4295 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4296 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4297 .build());
4298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4299 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4300 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4301 .build());
4302
4303 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4304 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4305 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4306
4307 window->assertNoEvents();
4308}
4309
4310TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4312 sp<FakeWindowHandle> window =
4313 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4314 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004315 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004316
4317 // Start a three-finger touchpad swipe
4318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4319 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4320 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4321 .build());
4322 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4323 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4324 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4325 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4326 .build());
4327 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4328 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4329 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4330 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4331 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4332 .build());
4333
4334 // Move the swipe a bit
4335 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4336 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4337 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4338 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4339 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4340 .build());
4341
4342 // End the swipe
4343 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4344 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4345 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4346 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4347 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4348 .build());
4349 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4350 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4351 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4352 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4353 .build());
4354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4355 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4356 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4357 .build());
4358
4359 window->assertNoEvents();
4360}
4361
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004362/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004363 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4364 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004365 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004366 */
4367TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4369 sp<FakeWindowHandle> window =
4370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4371 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004372 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004373
4374 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4376 .downTime(baseTime + 10)
4377 .eventTime(baseTime + 10)
4378 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4379 .build());
4380
4381 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4382
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004383 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004384 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004385
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004386 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004387
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004388 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4389 .downTime(baseTime + 10)
4390 .eventTime(baseTime + 30)
4391 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4392 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4393 .build());
4394
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004395 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4396
4397 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004398 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4399 .downTime(baseTime + 10)
4400 .eventTime(baseTime + 40)
4401 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4402 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4403 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004404
4405 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4406
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4408 .downTime(baseTime + 10)
4409 .eventTime(baseTime + 50)
4410 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4411 .build());
4412
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004413 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4414
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4416 .downTime(baseTime + 60)
4417 .eventTime(baseTime + 60)
4418 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4419 .build());
4420
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004421 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004422}
4423
4424/**
Hu Guo771a7692023-09-17 20:51:08 +08004425 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4426 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4427 * its coordinates should be converted by the transform of the windows of target screen.
4428 */
4429TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4430 // This case will create a window and a spy window on the default display and mirror
4431 // window on the second display. cancel event is sent through spy window pilferPointers
4432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4433
4434 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4435 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4436 spyWindowDefaultDisplay->setTrustedOverlay(true);
4437 spyWindowDefaultDisplay->setSpy(true);
4438
4439 sp<FakeWindowHandle> windowDefaultDisplay =
4440 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4441 ADISPLAY_ID_DEFAULT);
4442 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4443
4444 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4445 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4446
4447 // Add the windows to the dispatcher
4448 mDispatcher->onWindowInfosChanged(
4449 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4450 *windowSecondDisplay->getInfo()},
4451 {},
4452 0,
4453 0});
4454
4455 // Send down to ADISPLAY_ID_DEFAULT
4456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4457 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4458 {100, 100}))
4459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4460
4461 spyWindowDefaultDisplay->consumeMotionDown();
4462 windowDefaultDisplay->consumeMotionDown();
4463
4464 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4465
4466 // windowDefaultDisplay gets cancel
4467 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4468 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4469
4470 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4471 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4472 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4473 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4474 EXPECT_EQ(100, event->getX(0));
4475 EXPECT_EQ(100, event->getY(0));
4476}
4477
4478/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004479 * Ensure the correct coordinate spaces are used by InputDispatcher.
4480 *
4481 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4482 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4483 * space.
4484 */
4485class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4486public:
4487 void SetUp() override {
4488 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004489 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004490 }
4491
4492 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4493 gui::DisplayInfo info;
4494 info.displayId = displayId;
4495 info.transform = transform;
4496 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004497 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004498 }
4499
4500 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4501 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004502 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004503 }
4504
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004505 void removeAllWindowsAndDisplays() {
4506 mDisplayInfos.clear();
4507 mWindowInfos.clear();
4508 }
4509
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004510 // Set up a test scenario where the display has a scaled projection and there are two windows
4511 // on the display.
4512 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4513 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4514 // respectively.
4515 ui::Transform displayTransform;
4516 displayTransform.set(2, 0, 0, 4);
4517 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4518
4519 std::shared_ptr<FakeApplicationHandle> application =
4520 std::make_shared<FakeApplicationHandle>();
4521
4522 // Add two windows to the display. Their frames are represented in the display space.
4523 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004524 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4525 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004526 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4527 addWindow(firstWindow);
4528
4529 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004530 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4531 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004532 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4533 addWindow(secondWindow);
4534 return {std::move(firstWindow), std::move(secondWindow)};
4535 }
4536
4537private:
4538 std::vector<gui::DisplayInfo> mDisplayInfos;
4539 std::vector<gui::WindowInfo> mWindowInfos;
4540};
4541
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004542TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004543 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4544 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004545 // selected so that if the hit test was performed with the point and the bounds being in
4546 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004547 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4548 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4549 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004550
4551 firstWindow->consumeMotionDown();
4552 secondWindow->assertNoEvents();
4553}
4554
4555// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4556// the event should be treated as being in the logical display space.
4557TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4558 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4559 // Send down to the first window. The point is represented in the logical display space. The
4560 // point is selected so that if the hit test was done in logical display space, then it would
4561 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004562 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004563 PointF{75 * 2, 55 * 4});
4564
4565 firstWindow->consumeMotionDown();
4566 secondWindow->assertNoEvents();
4567}
4568
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004569// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4570// event should be treated as being in the logical display space.
4571TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4572 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4573
4574 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4575 ui::Transform injectedEventTransform;
4576 injectedEventTransform.set(matrix);
4577 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4578 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4579
4580 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4581 .displayId(ADISPLAY_ID_DEFAULT)
4582 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004583 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004584 .x(untransformedPoint.x)
4585 .y(untransformedPoint.y))
4586 .build();
4587 event.transform(matrix);
4588
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004589 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004590 InputEventInjectionSync::WAIT_FOR_RESULT);
4591
4592 firstWindow->consumeMotionDown();
4593 secondWindow->assertNoEvents();
4594}
4595
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4597 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4598
4599 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004600 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4601 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4602 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004603
4604 firstWindow->assertNoEvents();
4605 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004606 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004607 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4608
4609 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4610 EXPECT_EQ(300, event->getRawX(0));
4611 EXPECT_EQ(880, event->getRawY(0));
4612
4613 // Ensure that the x and y values are in the window's coordinate space.
4614 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4615 // the logical display space. This will be the origin of the window space.
4616 EXPECT_EQ(100, event->getX(0));
4617 EXPECT_EQ(80, event->getY(0));
4618}
4619
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004620TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4621 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4622 // The monitor will always receive events in the logical display's coordinate space, because
4623 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004624 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004625
4626 // Send down to the first window.
4627 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4628 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4629 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4630 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4631
4632 // Second pointer goes down on second window.
4633 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4634 ADISPLAY_ID_DEFAULT,
4635 {PointF{50, 100}, PointF{150, 220}}));
4636 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4637 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4638 {1, PointF{300, 880}}};
4639 monitor.consumeMotionEvent(
4640 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4641
4642 mDispatcher->cancelCurrentTouch();
4643
4644 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4645 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4646 monitor.consumeMotionEvent(
4647 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4648}
4649
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004650TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4651 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4652
4653 // Send down to the first window.
4654 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4655 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4656 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4657
4658 // The pointer is transferred to the second window, and the second window receives it in the
4659 // correct coordinate space.
4660 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4661 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4662 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4663}
4664
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004665TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4666 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4667
4668 // Send hover move to the second window, and ensure it shows up as hover enter.
4669 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4670 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4671 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4672 WithCoords(100, 80), WithRawCoords(300, 880)));
4673
4674 // Touch down at the same location and ensure a hover exit is synthesized.
4675 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4676 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4677 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4678 WithRawCoords(300, 880)));
4679 secondWindow->consumeMotionEvent(
4680 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4681 secondWindow->assertNoEvents();
4682 firstWindow->assertNoEvents();
4683}
4684
4685TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4686 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4687
4688 // Send hover enter to second window
4689 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4690 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4691 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4692 WithCoords(100, 80), WithRawCoords(300, 880)));
4693
4694 mDispatcher->cancelCurrentTouch();
4695
4696 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4697 WithRawCoords(300, 880)));
4698 secondWindow->assertNoEvents();
4699 firstWindow->assertNoEvents();
4700}
4701
Prabir Pradhan16463382023-10-12 23:03:19 +00004702TEST_F(InputDispatcherDisplayProjectionTest,
4703 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4704 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4705
4706 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4707 ui::Transform secondDisplayTransform;
4708 secondDisplayTransform.set(matrix);
4709 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4710
4711 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4712 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4713 addWindow(secondWindowClone);
4714
4715 // Send hover enter to second window
4716 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4717 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4718 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4719 WithCoords(100, 80), WithRawCoords(300, 880),
4720 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4721
4722 mDispatcher->cancelCurrentTouch();
4723
4724 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4725 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4726 WithRawCoords(300, 880),
4727 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4728 secondWindow->assertNoEvents();
4729 firstWindow->assertNoEvents();
4730}
4731
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004732/** Ensure consistent behavior of InputDispatcher in all orientations. */
4733class InputDispatcherDisplayOrientationFixture
4734 : public InputDispatcherDisplayProjectionTest,
4735 public ::testing::WithParamInterface<ui::Rotation> {};
4736
4737// This test verifies the touchable region of a window for all rotations of the display by tapping
4738// in different locations on the display, specifically points close to the four corners of a
4739// window.
4740TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4741 constexpr static int32_t displayWidth = 400;
4742 constexpr static int32_t displayHeight = 800;
4743
4744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4745
4746 const auto rotation = GetParam();
4747
4748 // Set up the display with the specified rotation.
4749 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4750 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4751 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4752 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4753 logicalDisplayWidth, logicalDisplayHeight);
4754 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4755
4756 // Create a window with its bounds determined in the logical display.
4757 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4758 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4759 sp<FakeWindowHandle> window =
4760 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4761 window->setFrame(frameInDisplay, displayTransform);
4762 addWindow(window);
4763
4764 // The following points in logical display space should be inside the window.
4765 static const std::array<vec2, 4> insidePoints{
4766 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4767 for (const auto pointInsideWindow : insidePoints) {
4768 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4769 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004770 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4771 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4772 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004773 window->consumeMotionDown();
4774
Prabir Pradhan678438e2023-04-13 19:32:51 +00004775 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4776 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4777 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004778 window->consumeMotionUp();
4779 }
4780
4781 // The following points in logical display space should be outside the window.
4782 static const std::array<vec2, 5> outsidePoints{
4783 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4784 for (const auto pointOutsideWindow : outsidePoints) {
4785 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4786 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004787 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4788 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4789 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004790
Prabir Pradhan678438e2023-04-13 19:32:51 +00004791 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4792 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4793 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004794 }
4795 window->assertNoEvents();
4796}
4797
4798// Run the precision tests for all rotations.
4799INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4800 InputDispatcherDisplayOrientationFixture,
4801 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4802 ui::ROTATION_270),
4803 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4804 return ftl::enum_string(testParamInfo.param);
4805 });
4806
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004807using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4808 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004809
4810class TransferTouchFixture : public InputDispatcherTest,
4811 public ::testing::WithParamInterface<TransferFunction> {};
4812
4813TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004815
4816 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004817 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004818 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4819 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004820 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004821 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004822 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4823 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004824 sp<FakeWindowHandle> wallpaper =
4825 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4826 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004827 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004828 mDispatcher->onWindowInfosChanged(
4829 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004830
4831 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004832 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4833 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004834
Svet Ganov5d3bc372020-01-26 23:11:07 -08004835 // Only the first window should get the down event
4836 firstWindow->consumeMotionDown();
4837 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004838 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004839
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004840 // Transfer touch to the second window
4841 TransferFunction f = GetParam();
4842 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4843 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004844 // The first window gets cancel and the second gets down
4845 firstWindow->consumeMotionCancel();
4846 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004847 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004848
4849 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004850 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4851 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004852 // The first window gets no events and the second gets up
4853 firstWindow->assertNoEvents();
4854 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004855 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004856}
4857
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004858/**
4859 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4860 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4861 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4862 * natural to the user.
4863 * In this test, we are sending a pointer to both spy window and first window. We then try to
4864 * transfer touch to the second window. The dispatcher should identify the first window as the
4865 * one that should lose the gesture, and therefore the action should be to move the gesture from
4866 * the first window to the second.
4867 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4868 * the other API, as well.
4869 */
4870TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4871 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4872
4873 // Create a couple of windows + a spy window
4874 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004875 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004876 spyWindow->setTrustedOverlay(true);
4877 spyWindow->setSpy(true);
4878 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004879 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004880 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004881 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004882
4883 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004884 mDispatcher->onWindowInfosChanged(
4885 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004886
4887 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004888 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4889 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004890 // Only the first window and spy should get the down event
4891 spyWindow->consumeMotionDown();
4892 firstWindow->consumeMotionDown();
4893
4894 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4895 // if f === 'transferTouch'.
4896 TransferFunction f = GetParam();
4897 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4898 ASSERT_TRUE(success);
4899 // The first window gets cancel and the second gets down
4900 firstWindow->consumeMotionCancel();
4901 secondWindow->consumeMotionDown();
4902
4903 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004904 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4905 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004906 // The first window gets no events and the second+spy get up
4907 firstWindow->assertNoEvents();
4908 spyWindow->consumeMotionUp();
4909 secondWindow->consumeMotionUp();
4910}
4911
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004912TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004914
4915 PointF touchPoint = {10, 10};
4916
4917 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004918 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004919 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4920 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004921 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004922 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004923 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4924 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004925 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004926
4927 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004928 mDispatcher->onWindowInfosChanged(
4929 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004930
4931 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004932 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4933 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4934 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004935 // Only the first window should get the down event
4936 firstWindow->consumeMotionDown();
4937 secondWindow->assertNoEvents();
4938
4939 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004940 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4941 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004942 // Only the first window should get the pointer down event
4943 firstWindow->consumeMotionPointerDown(1);
4944 secondWindow->assertNoEvents();
4945
4946 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004947 TransferFunction f = GetParam();
4948 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4949 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004950 // The first window gets cancel and the second gets down and pointer down
4951 firstWindow->consumeMotionCancel();
4952 secondWindow->consumeMotionDown();
4953 secondWindow->consumeMotionPointerDown(1);
4954
4955 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004956 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4957 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004958 // The first window gets nothing and the second gets pointer up
4959 firstWindow->assertNoEvents();
4960 secondWindow->consumeMotionPointerUp(1);
4961
4962 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004963 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4964 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004965 // The first window gets nothing and the second gets up
4966 firstWindow->assertNoEvents();
4967 secondWindow->consumeMotionUp();
4968}
4969
Arthur Hungc539dbb2022-12-08 07:45:36 +00004970TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4972
4973 // Create a couple of windows
4974 sp<FakeWindowHandle> firstWindow =
4975 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4976 ADISPLAY_ID_DEFAULT);
4977 firstWindow->setDupTouchToWallpaper(true);
4978 sp<FakeWindowHandle> secondWindow =
4979 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4980 ADISPLAY_ID_DEFAULT);
4981 secondWindow->setDupTouchToWallpaper(true);
4982
4983 sp<FakeWindowHandle> wallpaper1 =
4984 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4985 wallpaper1->setIsWallpaper(true);
4986
4987 sp<FakeWindowHandle> wallpaper2 =
4988 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4989 wallpaper2->setIsWallpaper(true);
4990 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004991 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4992 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4993 {},
4994 0,
4995 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004996
4997 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004998 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4999 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005000
5001 // Only the first window should get the down event
5002 firstWindow->consumeMotionDown();
5003 secondWindow->assertNoEvents();
5004 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5005 wallpaper2->assertNoEvents();
5006
5007 // Transfer touch focus to the second window
5008 TransferFunction f = GetParam();
5009 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5010 ASSERT_TRUE(success);
5011
5012 // The first window gets cancel and the second gets down
5013 firstWindow->consumeMotionCancel();
5014 secondWindow->consumeMotionDown();
5015 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5016 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5017
5018 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005019 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5020 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005021 // The first window gets no events and the second gets up
5022 firstWindow->assertNoEvents();
5023 secondWindow->consumeMotionUp();
5024 wallpaper1->assertNoEvents();
5025 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5026}
5027
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005028// For the cases of single pointer touch and two pointers non-split touch, the api's
5029// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5030// for the case where there are multiple pointers split across several windows.
5031INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5032 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005033 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5034 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005035 return dispatcher->transferTouch(destChannelToken,
5036 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005037 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005038 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5039 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005040 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005041 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005042 }));
5043
Svet Ganov5d3bc372020-01-26 23:11:07 -08005044TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005046
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005047 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005048 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5049 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005050 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005051
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005052 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005053 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5054 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005055 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005056
5057 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005058 mDispatcher->onWindowInfosChanged(
5059 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005060
5061 PointF pointInFirst = {300, 200};
5062 PointF pointInSecond = {300, 600};
5063
5064 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005065 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5066 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5067 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005068 // Only the first window should get the down event
5069 firstWindow->consumeMotionDown();
5070 secondWindow->assertNoEvents();
5071
5072 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005073 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5074 ADISPLAY_ID_DEFAULT,
5075 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005076 // The first window gets a move and the second a down
5077 firstWindow->consumeMotionMove();
5078 secondWindow->consumeMotionDown();
5079
5080 // Transfer touch focus to the second window
5081 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5082 // The first window gets cancel and the new gets pointer down (it already saw down)
5083 firstWindow->consumeMotionCancel();
5084 secondWindow->consumeMotionPointerDown(1);
5085
5086 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005087 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5088 ADISPLAY_ID_DEFAULT,
5089 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005090 // The first window gets nothing and the second gets pointer up
5091 firstWindow->assertNoEvents();
5092 secondWindow->consumeMotionPointerUp(1);
5093
5094 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005095 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5096 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005097 // The first window gets nothing and the second gets up
5098 firstWindow->assertNoEvents();
5099 secondWindow->consumeMotionUp();
5100}
5101
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005102// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5103// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5104// touch is not supported, so the touch should continue on those windows and the transferred-to
5105// window should get nothing.
5106TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5107 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5108
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005109 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005110 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5111 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005112 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005113
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005114 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005115 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5116 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005117 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005118
5119 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005120 mDispatcher->onWindowInfosChanged(
5121 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005122
5123 PointF pointInFirst = {300, 200};
5124 PointF pointInSecond = {300, 600};
5125
5126 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5129 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005130 // Only the first window should get the down event
5131 firstWindow->consumeMotionDown();
5132 secondWindow->assertNoEvents();
5133
5134 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005135 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5136 ADISPLAY_ID_DEFAULT,
5137 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005138 // The first window gets a move and the second a down
5139 firstWindow->consumeMotionMove();
5140 secondWindow->consumeMotionDown();
5141
5142 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005143 const bool transferred =
5144 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005145 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5146 ASSERT_FALSE(transferred);
5147 firstWindow->assertNoEvents();
5148 secondWindow->assertNoEvents();
5149
5150 // The rest of the dispatch should proceed as normal
5151 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005152 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5153 ADISPLAY_ID_DEFAULT,
5154 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005155 // The first window gets MOVE and the second gets pointer up
5156 firstWindow->consumeMotionMove();
5157 secondWindow->consumeMotionUp();
5158
5159 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5161 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005162 // The first window gets nothing and the second gets up
5163 firstWindow->consumeMotionUp();
5164 secondWindow->assertNoEvents();
5165}
5166
Arthur Hungabbb9d82021-09-01 14:52:30 +00005167// This case will create two windows and one mirrored window on the default display and mirror
5168// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5169// the windows info of second display before default display.
5170TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5171 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5172 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005173 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005174 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005175 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005176 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005177 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005178
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005179 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005180 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005181
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005182 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005183 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005184
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005185 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005186 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005187
5188 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005189 mDispatcher->onWindowInfosChanged(
5190 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5191 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5192 *secondWindowInPrimary->getInfo()},
5193 {},
5194 0,
5195 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005196
5197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005198 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005199 {50, 50}))
5200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5201
5202 // Window should receive motion event.
5203 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5204
5205 // Transfer touch focus
5206 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5207 secondWindowInPrimary->getToken()));
5208 // The first window gets cancel.
5209 firstWindowInPrimary->consumeMotionCancel();
5210 secondWindowInPrimary->consumeMotionDown();
5211
5212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005213 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005214 ADISPLAY_ID_DEFAULT, {150, 50}))
5215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5216 firstWindowInPrimary->assertNoEvents();
5217 secondWindowInPrimary->consumeMotionMove();
5218
5219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005220 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005221 {150, 50}))
5222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5223 firstWindowInPrimary->assertNoEvents();
5224 secondWindowInPrimary->consumeMotionUp();
5225}
5226
5227// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5228// 'transferTouch' api.
5229TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5231 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005232 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005233 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005234 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005235 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005236 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005237
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005238 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005239 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005240
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005241 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005242 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005243
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005244 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005245 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005246
5247 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005248 mDispatcher->onWindowInfosChanged(
5249 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5250 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5251 *secondWindowInPrimary->getInfo()},
5252 {},
5253 0,
5254 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005255
5256 // Touch on second display.
5257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5259 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005260 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5261
5262 // Window should receive motion event.
5263 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5264
5265 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005266 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005267
5268 // The first window gets cancel.
5269 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5270 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5271
5272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005273 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005274 SECOND_DISPLAY_ID, {150, 50}))
5275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5276 firstWindowInPrimary->assertNoEvents();
5277 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5278
5279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005280 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5282 firstWindowInPrimary->assertNoEvents();
5283 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5284}
5285
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005286TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005288 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5289 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005290
Vishnu Nair47074b82020-08-14 11:54:47 -07005291 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005292 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005293 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005294
5295 window->consumeFocusEvent(true);
5296
Prabir Pradhan678438e2023-04-13 19:32:51 +00005297 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005298
5299 // Window should receive key down event.
5300 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005301
5302 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005303 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005304 mFakePolicy->assertUserActivityPoked();
5305}
5306
5307TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5309 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5310 "Fake Window", ADISPLAY_ID_DEFAULT);
5311
5312 window->setDisableUserActivity(true);
5313 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005314 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005315 setFocusedWindow(window);
5316
5317 window->consumeFocusEvent(true);
5318
5319 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5320
5321 // Window should receive key down event.
5322 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5323
5324 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005325 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005326 mFakePolicy->assertUserActivityNotPoked();
5327}
5328
5329TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5330 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5331 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5332 "Fake Window", ADISPLAY_ID_DEFAULT);
5333
5334 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005335 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005336 setFocusedWindow(window);
5337
5338 window->consumeFocusEvent(true);
5339
5340 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5341 mDispatcher->waitForIdle();
5342
5343 // System key is not passed down
5344 window->assertNoEvents();
5345
5346 // Should have poked user activity
5347 mFakePolicy->assertUserActivityPoked();
5348}
5349
5350TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5352 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5353 "Fake Window", ADISPLAY_ID_DEFAULT);
5354
5355 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005357 setFocusedWindow(window);
5358
5359 window->consumeFocusEvent(true);
5360
5361 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5362 mDispatcher->waitForIdle();
5363
5364 // System key is not passed down
5365 window->assertNoEvents();
5366
5367 // Should have poked user activity
5368 mFakePolicy->assertUserActivityPoked();
5369}
5370
5371TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5373 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5374 "Fake Window", ADISPLAY_ID_DEFAULT);
5375
5376 window->setDisableUserActivity(true);
5377 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005378 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005379 setFocusedWindow(window);
5380
5381 window->consumeFocusEvent(true);
5382
5383 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5384 mDispatcher->waitForIdle();
5385
5386 // System key is not passed down
5387 window->assertNoEvents();
5388
5389 // Should have poked user activity
5390 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005391}
5392
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005393TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5396 "Fake Window", ADISPLAY_ID_DEFAULT);
5397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005398 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005399
5400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005401 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005402 ADISPLAY_ID_DEFAULT, {100, 100}))
5403 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5404
5405 window->consumeMotionEvent(
5406 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5407
5408 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005409 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005410 mFakePolicy->assertUserActivityPoked();
5411}
5412
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005413TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5416 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005417
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005419
Prabir Pradhan678438e2023-04-13 19:32:51 +00005420 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005421 mDispatcher->waitForIdle();
5422
5423 window->assertNoEvents();
5424}
5425
5426// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5427TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005429 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5430 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005432 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005433
5434 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005435 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005436 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005437 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5438 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005439
5440 // Window should receive only the motion event
5441 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5442 window->assertNoEvents(); // Key event or focus event will not be received
5443}
5444
arthurhungea3f4fc2020-12-21 23:18:53 +08005445TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5447
arthurhungea3f4fc2020-12-21 23:18:53 +08005448 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005449 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5450 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005451 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005452
arthurhungea3f4fc2020-12-21 23:18:53 +08005453 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005454 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5455 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005456 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005457
5458 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005459 mDispatcher->onWindowInfosChanged(
5460 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005461
5462 PointF pointInFirst = {300, 200};
5463 PointF pointInSecond = {300, 600};
5464
5465 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005466 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5467 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5468 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005469 // Only the first window should get the down event
5470 firstWindow->consumeMotionDown();
5471 secondWindow->assertNoEvents();
5472
5473 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005474 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5475 ADISPLAY_ID_DEFAULT,
5476 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005477 // The first window gets a move and the second a down
5478 firstWindow->consumeMotionMove();
5479 secondWindow->consumeMotionDown();
5480
5481 // Send pointer cancel to the second window
5482 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005483 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005484 {pointInFirst, pointInSecond});
5485 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005486 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005487 // The first window gets move and the second gets cancel.
5488 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5489 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5490
5491 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005492 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5493 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005494 // The first window gets up and the second gets nothing.
5495 firstWindow->consumeMotionUp();
5496 secondWindow->assertNoEvents();
5497}
5498
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005499TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5501
5502 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005503 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005504 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005505 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5506 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5507 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5508
Harry Cutts33476232023-01-30 19:57:29 +00005509 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005510 window->assertNoEvents();
5511 mDispatcher->waitForIdle();
5512}
5513
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005514using InputDispatcherMonitorTest = InputDispatcherTest;
5515
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005516/**
5517 * Two entities that receive touch: A window, and a global monitor.
5518 * The touch goes to the window, and then the window disappears.
5519 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5520 * for the monitor, as well.
5521 * 1. foregroundWindow
5522 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5523 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005524TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5526 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005527 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005528
Prabir Pradhanfb549072023-10-05 19:17:36 +00005529 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005530
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005533 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005534 {100, 200}))
5535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5536
5537 // Both the foreground window and the global monitor should receive the touch down
5538 window->consumeMotionDown();
5539 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5540
5541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005542 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005543 ADISPLAY_ID_DEFAULT, {110, 200}))
5544 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5545
5546 window->consumeMotionMove();
5547 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5548
5549 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005550 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005551 window->consumeMotionCancel();
5552 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5553
5554 // If more events come in, there will be no more foreground window to send them to. This will
5555 // cause a cancel for the monitor, as well.
5556 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005557 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005558 ADISPLAY_ID_DEFAULT, {120, 200}))
5559 << "Injection should fail because the window was removed";
5560 window->assertNoEvents();
5561 // Global monitor now gets the cancel
5562 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5563}
5564
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005565TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005567 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5568 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005569 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005570
Prabir Pradhanfb549072023-10-05 19:17:36 +00005571 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005572
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005574 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005576 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005577 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005578}
5579
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005580TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005581 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005582
Chris Yea209fde2020-07-22 13:54:51 -07005583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5585 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005586 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005587
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005589 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005591 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005592 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005593
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005594 // Pilfer pointers from the monitor.
5595 // This should not do anything and the window should continue to receive events.
5596 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005597
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005599 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005600 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005601 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005602
5603 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5604 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005605}
5606
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005607TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005609 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5610 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005612 window->setWindowOffset(20, 40);
5613 window->setWindowTransform(0, 1, -1, 0);
5614
Prabir Pradhanfb549072023-10-05 19:17:36 +00005615 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005616
5617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5620 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5621 MotionEvent* event = monitor.consumeMotion();
5622 // Even though window has transform, gesture monitor must not.
5623 ASSERT_EQ(ui::Transform(), event->getTransform());
5624}
5625
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005626TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005628 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005629
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005630 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005631 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005632 << "Injection should fail if there is a monitor, but no touchable window";
5633 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005634}
5635
chaviw81e2bb92019-12-18 15:03:51 -08005636TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005637 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005638 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5639 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005640
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005641 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005642
5643 NotifyMotionArgs motionArgs =
5644 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5645 ADISPLAY_ID_DEFAULT);
5646
Prabir Pradhan678438e2023-04-13 19:32:51 +00005647 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005648 // Window should receive motion down event.
5649 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5650
5651 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005652 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005653 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5654 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5655 motionArgs.pointerCoords[0].getX() - 10);
5656
Prabir Pradhan678438e2023-04-13 19:32:51 +00005657 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005658 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005659 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005660}
5661
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005662/**
5663 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5664 * the device default right away. In the test scenario, we check both the default value,
5665 * and the action of enabling / disabling.
5666 */
5667TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005669 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5670 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005671 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005672
5673 // Set focused application.
5674 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005675 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005676
5677 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005678 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005679 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005680 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005681
5682 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005683 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005685 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005686
5687 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005688 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005689 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005690 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005691 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005693 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005694 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005695
5696 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005697 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005699 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005700
5701 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005702 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005703 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005704 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005705 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005707 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005708 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005709
5710 window->assertNoEvents();
5711}
5712
Gang Wange9087892020-01-07 12:17:14 -05005713TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005715 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5716 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005717
5718 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005719 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005720
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005721 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005722 setFocusedWindow(window);
5723
Harry Cutts33476232023-01-30 19:57:29 +00005724 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005725
Prabir Pradhan678438e2023-04-13 19:32:51 +00005726 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5727 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005728
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005729 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005730 ASSERT_NE(event, nullptr);
5731
5732 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5733 ASSERT_NE(verified, nullptr);
5734 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5735
5736 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5737 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5738 ASSERT_EQ(keyArgs.source, verified->source);
5739 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5740
5741 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5742
5743 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005744 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005745 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005746 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5747 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5748 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5749 ASSERT_EQ(0, verifiedKey.repeatCount);
5750}
5751
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005752TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5755 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005756
5757 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5758
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005759 ui::Transform transform;
5760 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5761
5762 gui::DisplayInfo displayInfo;
5763 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5764 displayInfo.transform = transform;
5765
Patrick Williamsd828f302023-04-28 17:52:08 -05005766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005767
Prabir Pradhan678438e2023-04-13 19:32:51 +00005768 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005769 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5770 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005771 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005772
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005773 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005774 ASSERT_NE(event, nullptr);
5775
5776 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5777 ASSERT_NE(verified, nullptr);
5778 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5779
5780 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5781 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5782 EXPECT_EQ(motionArgs.source, verified->source);
5783 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5784
5785 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5786
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005787 const vec2 rawXY =
5788 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5789 motionArgs.pointerCoords[0].getXYValue());
5790 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5791 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005792 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005793 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005794 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005795 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5796 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5797}
5798
chaviw09c8d2d2020-08-24 15:48:26 -07005799/**
5800 * Ensure that separate calls to sign the same data are generating the same key.
5801 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5802 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5803 * tests.
5804 */
5805TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5806 KeyEvent event = getTestKeyEvent();
5807 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5808
5809 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5810 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5811 ASSERT_EQ(hmac1, hmac2);
5812}
5813
5814/**
5815 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5816 */
5817TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5818 KeyEvent event = getTestKeyEvent();
5819 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5820 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5821
5822 verifiedEvent.deviceId += 1;
5823 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5824
5825 verifiedEvent.source += 1;
5826 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5827
5828 verifiedEvent.eventTimeNanos += 1;
5829 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5830
5831 verifiedEvent.displayId += 1;
5832 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5833
5834 verifiedEvent.action += 1;
5835 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5836
5837 verifiedEvent.downTimeNanos += 1;
5838 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5839
5840 verifiedEvent.flags += 1;
5841 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5842
5843 verifiedEvent.keyCode += 1;
5844 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5845
5846 verifiedEvent.scanCode += 1;
5847 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5848
5849 verifiedEvent.metaState += 1;
5850 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5851
5852 verifiedEvent.repeatCount += 1;
5853 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5854}
5855
Vishnu Nair958da932020-08-21 17:12:37 -07005856TEST_F(InputDispatcherTest, SetFocusedWindow) {
5857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5858 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005859 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005860 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005861 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005862 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5863
5864 // Top window is also focusable but is not granted focus.
5865 windowTop->setFocusable(true);
5866 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005867 mDispatcher->onWindowInfosChanged(
5868 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005869 setFocusedWindow(windowSecond);
5870
5871 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005873 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005874
5875 // Focused window should receive event.
5876 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5877 windowTop->assertNoEvents();
5878}
5879
5880TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5882 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005883 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005884 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5885
5886 window->setFocusable(true);
5887 // Release channel for window is no longer valid.
5888 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005889 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005890 setFocusedWindow(window);
5891
5892 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005893 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005894
5895 // window channel is invalid, so it should not receive any input event.
5896 window->assertNoEvents();
5897}
5898
5899TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5901 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005902 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005903 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005904 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5905
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005907 setFocusedWindow(window);
5908
5909 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005910 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005911
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005912 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005913 window->assertNoEvents();
5914}
5915
5916TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5917 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5918 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005919 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005920 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005921 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005922 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5923
5924 windowTop->setFocusable(true);
5925 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005926 mDispatcher->onWindowInfosChanged(
5927 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005928 setFocusedWindow(windowTop);
5929 windowTop->consumeFocusEvent(true);
5930
Chavi Weingarten847e8512023-03-29 00:26:09 +00005931 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005932 mDispatcher->onWindowInfosChanged(
5933 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005934 windowSecond->consumeFocusEvent(true);
5935 windowTop->consumeFocusEvent(false);
5936
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005939
5940 // Focused window should receive event.
5941 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5942}
5943
Chavi Weingarten847e8512023-03-29 00:26:09 +00005944TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5946 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005947 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005948 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005949 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005950 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5951
5952 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005953 windowSecond->setFocusable(false);
5954 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005955 mDispatcher->onWindowInfosChanged(
5956 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005957 setFocusedWindow(windowTop);
5958 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005959
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005961 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005962
5963 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005964 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005965 windowSecond->assertNoEvents();
5966}
5967
5968TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5970 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005971 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005972 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005973 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5974 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005975 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5976
5977 window->setFocusable(true);
5978 previousFocusedWindow->setFocusable(true);
5979 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005980 mDispatcher->onWindowInfosChanged(
5981 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005982 setFocusedWindow(previousFocusedWindow);
5983 previousFocusedWindow->consumeFocusEvent(true);
5984
5985 // Requesting focus on invisible window takes focus from currently focused window.
5986 setFocusedWindow(window);
5987 previousFocusedWindow->consumeFocusEvent(false);
5988
5989 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005991 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5992 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005993
5994 // Window does not get focus event or key down.
5995 window->assertNoEvents();
5996
5997 // Window becomes visible.
5998 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005999 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006000
6001 // Window receives focus event.
6002 window->consumeFocusEvent(true);
6003 // Focused window receives key down.
6004 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6005}
6006
Vishnu Nair599f1412021-06-21 10:39:58 -07006007TEST_F(InputDispatcherTest, DisplayRemoved) {
6008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6009 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006010 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006011 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6012
6013 // window is granted focus.
6014 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006016 setFocusedWindow(window);
6017 window->consumeFocusEvent(true);
6018
6019 // When a display is removed window loses focus.
6020 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6021 window->consumeFocusEvent(false);
6022}
6023
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006024/**
6025 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6026 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6027 * of the 'slipperyEnterWindow'.
6028 *
6029 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6030 * a way so that the touched location is no longer covered by the top window.
6031 *
6032 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6033 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6034 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6035 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6036 * with ACTION_DOWN).
6037 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6038 * window moved itself away from the touched location and had Flag::SLIPPERY.
6039 *
6040 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6041 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6042 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6043 *
6044 * In this test, we ensure that the event received by the bottom window has
6045 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6046 */
6047TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006048 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006049 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006050
6051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6052 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6053
6054 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006055 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006056 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006057 // Make sure this one overlaps the bottom window
6058 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6059 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6060 // one. Windows with the same owner are not considered to be occluding each other.
6061 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6062
6063 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006064 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006065 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6066
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006067 mDispatcher->onWindowInfosChanged(
6068 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006069
6070 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006071 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6072 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6073 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006074 slipperyExitWindow->consumeMotionDown();
6075 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006076 mDispatcher->onWindowInfosChanged(
6077 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006078
Prabir Pradhan678438e2023-04-13 19:32:51 +00006079 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6080 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6081 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006082
6083 slipperyExitWindow->consumeMotionCancel();
6084
6085 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6086 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6087}
6088
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006089/**
6090 * Two windows, one on the left and another on the right. The left window is slippery. The right
6091 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6092 * touch moves from the left window into the right window, the gesture should continue to go to the
6093 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6094 * reproduces a crash.
6095 */
6096TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6098
6099 sp<FakeWindowHandle> leftSlipperyWindow =
6100 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6101 leftSlipperyWindow->setSlippery(true);
6102 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6103
6104 sp<FakeWindowHandle> rightDropTouchesWindow =
6105 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6106 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6107 rightDropTouchesWindow->setDropInput(true);
6108
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006109 mDispatcher->onWindowInfosChanged(
6110 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006111
6112 // Start touch in the left window
6113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6114 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6115 .build());
6116 leftSlipperyWindow->consumeMotionDown();
6117
6118 // And move it into the right window
6119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6120 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6121 .build());
6122
6123 // Since the right window isn't eligible to receive input, touch does not slip.
6124 // The left window continues to receive the gesture.
6125 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6126 rightDropTouchesWindow->assertNoEvents();
6127}
6128
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006129/**
6130 * A single window is on screen first. Touch is injected into that window. Next, a second window
6131 * appears. Since the first window is slippery, touch will move from the first window to the second.
6132 */
6133TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6134 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6135 sp<FakeWindowHandle> originalWindow =
6136 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6137 originalWindow->setFrame(Rect(0, 0, 200, 200));
6138 originalWindow->setSlippery(true);
6139
6140 sp<FakeWindowHandle> appearingWindow =
6141 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6142 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6143
6144 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6145
6146 // Touch down on the original window
6147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6148 injectMotionEvent(*mDispatcher,
6149 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6150 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6151 .build()));
6152 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6153
6154 // Now, a new window appears. This could be, for example, a notification shade that appears
6155 // after user starts to drag down on the launcher window.
6156 mDispatcher->onWindowInfosChanged(
6157 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6159 injectMotionEvent(*mDispatcher,
6160 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6161 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6162 .build()));
6163 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6164 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6166 injectMotionEvent(*mDispatcher,
6167 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6168 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6169 .build()));
6170 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6171
6172 originalWindow->assertNoEvents();
6173 appearingWindow->assertNoEvents();
6174}
6175
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006176TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006177 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6179
6180 sp<FakeWindowHandle> leftWindow =
6181 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6182 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006183 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006184
6185 sp<FakeWindowHandle> rightSpy =
6186 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6187 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006188 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006189 rightSpy->setSpy(true);
6190 rightSpy->setTrustedOverlay(true);
6191
6192 sp<FakeWindowHandle> rightWindow =
6193 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6194 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006195 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006196
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006197 mDispatcher->onWindowInfosChanged(
6198 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006199
6200 // Touch in the left window
6201 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6202 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6203 .build());
6204 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6205 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006206 ASSERT_NO_FATAL_FAILURE(
6207 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006208
6209 // Touch another finger over the right windows
6210 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6211 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6212 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6213 .build());
6214 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6215 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6216 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6217 mDispatcher->waitForIdle();
6218 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006219 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6220 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006221
6222 // Release finger over left window. The UP actions are not treated as device interaction.
6223 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6224 // is part of the UP action, we do not treat this as device interaction.
6225 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6226 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6227 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6228 .build());
6229 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6230 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6231 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6232 mDispatcher->waitForIdle();
6233 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6234
6235 // Move remaining finger
6236 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6237 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6238 .build());
6239 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6240 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6241 mDispatcher->waitForIdle();
6242 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006243 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006244
6245 // Release all fingers
6246 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6247 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6248 .build());
6249 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6250 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6251 mDispatcher->waitForIdle();
6252 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6253}
6254
6255TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6257
6258 sp<FakeWindowHandle> window =
6259 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6260 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006261 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006262
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006263 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006264 setFocusedWindow(window);
6265 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6266
6267 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6268 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6269 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006270 ASSERT_NO_FATAL_FAILURE(
6271 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006272
6273 // The UP actions are not treated as device interaction.
6274 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6275 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6276 mDispatcher->waitForIdle();
6277 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6278}
6279
Garfield Tan1c7bc862020-01-28 13:24:04 -08006280class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6281protected:
6282 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6283 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6284
Chris Yea209fde2020-07-22 13:54:51 -07006285 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006286 sp<FakeWindowHandle> mWindow;
6287
6288 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006289 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006290 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006291 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006292 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006293 ASSERT_EQ(OK, mDispatcher->start());
6294
6295 setUpWindow();
6296 }
6297
6298 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006299 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006300 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006301
Vishnu Nair47074b82020-08-14 11:54:47 -07006302 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006303 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006304 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006305 mWindow->consumeFocusEvent(true);
6306 }
6307
Chris Ye2ad95392020-09-01 13:44:44 -07006308 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006309 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006310 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006311 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006312 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006313
6314 // Window should receive key down event.
6315 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6316 }
6317
6318 void expectKeyRepeatOnce(int32_t repeatCount) {
6319 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006320 mWindow->consumeKeyEvent(
6321 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006322 }
6323
Chris Ye2ad95392020-09-01 13:44:44 -07006324 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006325 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006326 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006327 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006328 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006329
6330 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006331 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006332 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006333 }
6334};
6335
6336TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006337 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006338 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6339 expectKeyRepeatOnce(repeatCount);
6340 }
6341}
6342
6343TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006344 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006345 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6346 expectKeyRepeatOnce(repeatCount);
6347 }
Harry Cutts33476232023-01-30 19:57:29 +00006348 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006349 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006350 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6351 expectKeyRepeatOnce(repeatCount);
6352 }
6353}
6354
6355TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006356 sendAndConsumeKeyDown(/*deviceId=*/1);
6357 expectKeyRepeatOnce(/*repeatCount=*/1);
6358 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006359 mWindow->assertNoEvents();
6360}
6361
6362TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006363 sendAndConsumeKeyDown(/*deviceId=*/1);
6364 expectKeyRepeatOnce(/*repeatCount=*/1);
6365 sendAndConsumeKeyDown(/*deviceId=*/2);
6366 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006367 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006368 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006369 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006370 expectKeyRepeatOnce(/*repeatCount=*/2);
6371 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006372 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006373 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006374 mWindow->assertNoEvents();
6375}
6376
6377TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006378 sendAndConsumeKeyDown(/*deviceId=*/1);
6379 expectKeyRepeatOnce(/*repeatCount=*/1);
6380 sendAndConsumeKeyDown(/*deviceId=*/2);
6381 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006382 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006383 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006384 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006385 mWindow->assertNoEvents();
6386}
6387
liushenxiang42232912021-05-21 20:24:09 +08006388TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6389 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006390 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006391 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006392 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6393 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6394 mWindow->assertNoEvents();
6395}
6396
Garfield Tan1c7bc862020-01-28 13:24:04 -08006397TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006398 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006399 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006400 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006401 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006402 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6403 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6404 IdGenerator::getSource(repeatEvent->getId()));
6405 }
6406}
6407
6408TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006409 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006410 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006411
6412 std::unordered_set<int32_t> idSet;
6413 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006414 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006415 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6416 int32_t id = repeatEvent->getId();
6417 EXPECT_EQ(idSet.end(), idSet.find(id));
6418 idSet.insert(id);
6419 }
6420}
6421
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006422/* Test InputDispatcher for MultiDisplay */
6423class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6424public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006425 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006426 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006427
Chris Yea209fde2020-07-22 13:54:51 -07006428 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006429 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006430 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006431
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006432 // Set focus window for primary display, but focused display would be second one.
6433 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006434 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006435 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6436
Vishnu Nair958da932020-08-21 17:12:37 -07006437 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006438 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006439
Chris Yea209fde2020-07-22 13:54:51 -07006440 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006441 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006442 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006443 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006444 // Set focus display to second one.
6445 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6446 // Set focus window for second display.
6447 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006448 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006449 mDispatcher->onWindowInfosChanged(
6450 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006451 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006452 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006453 }
6454
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006455 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006456 InputDispatcherTest::TearDown();
6457
Chris Yea209fde2020-07-22 13:54:51 -07006458 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006459 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006460 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006461 windowInSecondary.clear();
6462 }
6463
6464protected:
Chris Yea209fde2020-07-22 13:54:51 -07006465 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006466 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006467 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006468 sp<FakeWindowHandle> windowInSecondary;
6469};
6470
6471TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6472 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006476 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006477 windowInSecondary->assertNoEvents();
6478
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006479 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006481 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006483 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006484 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006485}
6486
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006487TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006488 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006490 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006491 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006492 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006493 windowInSecondary->assertNoEvents();
6494
6495 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006497 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006498 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006499 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006500
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006501 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006502 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006503
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006504 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006505 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006506 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006507
6508 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006509 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006510 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006511 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006512 windowInSecondary->assertNoEvents();
6513}
6514
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006515// Test per-display input monitors for motion event.
6516TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006517 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006518 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006519 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006520 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006521
6522 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006524 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006526 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006527 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006528 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006529 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006530
6531 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006533 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006535 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006536 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006537 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006538 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006539
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006540 // Lift up the touch from the second display
6541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006542 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6544 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6545 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6546
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006547 // Test inject a non-pointer motion event.
6548 // If specific a display, it will dispatch to the focused window of particular display,
6549 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006551 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006553 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006554 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006555 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006556 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006557}
6558
6559// Test per-display input monitors for key event.
6560TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006561 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006562 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006563 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006564 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006565 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006566
6567 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006569 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006570 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006571 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006572 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006573 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006574}
6575
Vishnu Nair958da932020-08-21 17:12:37 -07006576TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6577 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006578 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006579 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006580 mDispatcher->onWindowInfosChanged(
6581 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6582 *windowInSecondary->getInfo()},
6583 {},
6584 0,
6585 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006586 setFocusedWindow(secondWindowInPrimary);
6587 windowInPrimary->consumeFocusEvent(false);
6588 secondWindowInPrimary->consumeFocusEvent(true);
6589
6590 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6592 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006593 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006594 windowInPrimary->assertNoEvents();
6595 windowInSecondary->assertNoEvents();
6596 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6597}
6598
Arthur Hungdfd528e2021-12-08 13:23:04 +00006599TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6600 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006601 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006602 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006603 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006604
6605 // Test touch down on primary display.
6606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006607 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6609 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6610 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6611
6612 // Test touch down on second display.
6613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006614 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006615 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6616 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6617 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6618
6619 // Trigger cancel touch.
6620 mDispatcher->cancelCurrentTouch();
6621 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6622 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6623 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6624 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6625
6626 // Test inject a move motion event, no window/monitor should receive the event.
6627 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006628 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006629 ADISPLAY_ID_DEFAULT, {110, 200}))
6630 << "Inject motion event should return InputEventInjectionResult::FAILED";
6631 windowInPrimary->assertNoEvents();
6632 monitorInPrimary.assertNoEvents();
6633
6634 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006635 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006636 SECOND_DISPLAY_ID, {110, 200}))
6637 << "Inject motion event should return InputEventInjectionResult::FAILED";
6638 windowInSecondary->assertNoEvents();
6639 monitorInSecondary.assertNoEvents();
6640}
6641
Jackal Guof9696682018-10-05 12:23:23 +08006642class InputFilterTest : public InputDispatcherTest {
6643protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006644 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6645 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006646 NotifyMotionArgs motionArgs;
6647
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006648 motionArgs =
6649 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006650 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006651 motionArgs =
6652 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006653 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006654 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006655 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006656 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006657 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006658 } else {
6659 mFakePolicy->assertFilterInputEventWasNotCalled();
6660 }
6661 }
6662
6663 void testNotifyKey(bool expectToBeFiltered) {
6664 NotifyKeyArgs keyArgs;
6665
6666 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006667 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006668 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006669 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006670 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006671
6672 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006673 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006674 } else {
6675 mFakePolicy->assertFilterInputEventWasNotCalled();
6676 }
6677 }
6678};
6679
6680// Test InputFilter for MotionEvent
6681TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6682 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006683 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6684 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006685
6686 // Enable InputFilter
6687 mDispatcher->setInputFilterEnabled(true);
6688 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006689 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6690 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006691
6692 // Disable InputFilter
6693 mDispatcher->setInputFilterEnabled(false);
6694 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006695 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6696 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006697}
6698
6699// Test InputFilter for KeyEvent
6700TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6701 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006702 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006703
6704 // Enable InputFilter
6705 mDispatcher->setInputFilterEnabled(true);
6706 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006707 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006708
6709 // Disable InputFilter
6710 mDispatcher->setInputFilterEnabled(false);
6711 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006712 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006713}
6714
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006715// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6716// logical display coordinate space.
6717TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6718 ui::Transform firstDisplayTransform;
6719 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6720 ui::Transform secondDisplayTransform;
6721 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6722
6723 std::vector<gui::DisplayInfo> displayInfos(2);
6724 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6725 displayInfos[0].transform = firstDisplayTransform;
6726 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6727 displayInfos[1].transform = secondDisplayTransform;
6728
Patrick Williamsd828f302023-04-28 17:52:08 -05006729 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006730
6731 // Enable InputFilter
6732 mDispatcher->setInputFilterEnabled(true);
6733
6734 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006735 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6736 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006737}
6738
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006739class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6740protected:
6741 virtual void SetUp() override {
6742 InputDispatcherTest::SetUp();
6743
6744 /**
6745 * We don't need to enable input filter to test the injected event policy, but we enabled it
6746 * here to make the tests more realistic, since this policy only matters when inputfilter is
6747 * on.
6748 */
6749 mDispatcher->setInputFilterEnabled(true);
6750
6751 std::shared_ptr<InputApplicationHandle> application =
6752 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006753 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6754 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006755
6756 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6757 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006758 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006759 setFocusedWindow(mWindow);
6760 mWindow->consumeFocusEvent(true);
6761 }
6762
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006763 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6764 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006765 KeyEvent event;
6766
6767 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6768 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6769 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006770 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006771 const int32_t additionalPolicyFlags =
6772 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006775 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006776 policyFlags | additionalPolicyFlags));
6777
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006778 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006779 }
6780
6781 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6782 int32_t flags) {
6783 MotionEvent event;
6784 PointerProperties pointerProperties[1];
6785 PointerCoords pointerCoords[1];
6786 pointerProperties[0].clear();
6787 pointerProperties[0].id = 0;
6788 pointerCoords[0].clear();
6789 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6790 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6791
6792 ui::Transform identityTransform;
6793 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6794 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6795 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6796 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6797 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006798 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006799 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006800 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006801
6802 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006804 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006805 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006806 policyFlags | additionalPolicyFlags));
6807
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006808 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006809 }
6810
6811private:
6812 sp<FakeWindowHandle> mWindow;
6813};
6814
6815TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006816 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6817 // filter. Without it, the event will no different from a regularly injected event, and the
6818 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006819 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6820 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006821}
6822
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006823TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006824 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006825 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006826 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6827}
6828
6829TEST_F(InputFilterInjectionPolicyTest,
6830 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6831 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006832 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006833 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006834}
6835
6836TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006837 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6838 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006839}
6840
chaviwfd6d3512019-03-25 13:23:49 -07006841class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006842 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006843 InputDispatcherTest::SetUp();
6844
Chris Yea209fde2020-07-22 13:54:51 -07006845 std::shared_ptr<FakeApplicationHandle> application =
6846 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006847 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006848 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006849 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006850
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006851 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006852 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006853 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006854
6855 // Set focused application.
6856 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006857 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006858
6859 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006860 mDispatcher->onWindowInfosChanged(
6861 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006862 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006863 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006864 }
6865
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006866 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006867 InputDispatcherTest::TearDown();
6868
6869 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006870 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006871 }
6872
6873protected:
6874 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006875 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006876 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006877};
6878
6879// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6880// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6881// the onPointerDownOutsideFocus callback.
6882TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006885 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006887 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006888
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006889 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006890 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6891}
6892
6893// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6894// DOWN on the window that doesn't have focus. Ensure no window received the
6895// onPointerDownOutsideFocus callback.
6896TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006898 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6899 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006901 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006902
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006903 ASSERT_TRUE(mDispatcher->waitForIdle());
6904 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006905}
6906
6907// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6908// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6909TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006911 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006912 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006913 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006914
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006915 ASSERT_TRUE(mDispatcher->waitForIdle());
6916 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006917}
6918
6919// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6920// DOWN on the window that already has focus. Ensure no window received the
6921// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006922TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006924 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006925 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006927 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006928
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006929 ASSERT_TRUE(mDispatcher->waitForIdle());
6930 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006931}
6932
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006933// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6934// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6935TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6936 const MotionEvent event =
6937 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6938 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006940 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6941 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6944 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6945
6946 ASSERT_TRUE(mDispatcher->waitForIdle());
6947 mFakePolicy->assertOnPointerDownWasNotCalled();
6948 // Ensure that the unfocused window did not receive any FOCUS events.
6949 mUnfocusedWindow->assertNoEvents();
6950}
6951
chaviwaf87b3e2019-10-01 16:59:28 -07006952// These tests ensures we can send touch events to a single client when there are multiple input
6953// windows that point to the same client token.
6954class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6955 virtual void SetUp() override {
6956 InputDispatcherTest::SetUp();
6957
Chris Yea209fde2020-07-22 13:54:51 -07006958 std::shared_ptr<FakeApplicationHandle> application =
6959 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006960 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6961 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006962 mWindow1->setFrame(Rect(0, 0, 100, 100));
6963
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006964 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6965 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006966 mWindow2->setFrame(Rect(100, 100, 200, 200));
6967
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006968 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006969 }
6970
6971protected:
6972 sp<FakeWindowHandle> mWindow1;
6973 sp<FakeWindowHandle> mWindow2;
6974
6975 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006976 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006977 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6978 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006979 }
6980
6981 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6982 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006983 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006984 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006985
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006986 ASSERT_NE(nullptr, motionEvent)
6987 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006988
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006989 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006990 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006991
6992 for (size_t i = 0; i < points.size(); i++) {
6993 float expectedX = points[i].x;
6994 float expectedY = points[i].y;
6995
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006996 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006997 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006998 << ", got " << motionEvent->getX(i);
6999 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007000 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007001 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007002 }
7003 }
chaviw9eaa22c2020-07-01 16:21:27 -07007004
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007005 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007006 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007007 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7008 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007009
7010 // Always consume from window1 since it's the window that has the InputReceiver
7011 consumeMotionEvent(mWindow1, action, expectedPoints);
7012 }
chaviwaf87b3e2019-10-01 16:59:28 -07007013};
7014
7015TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7016 // Touch Window 1
7017 PointF touchedPoint = {10, 10};
7018 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007019 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007020
7021 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007022 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007023
7024 // Touch Window 2
7025 touchedPoint = {150, 150};
7026 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007027 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007028}
7029
chaviw9eaa22c2020-07-01 16:21:27 -07007030TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7031 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007032 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007033 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007034
7035 // Touch Window 1
7036 PointF touchedPoint = {10, 10};
7037 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007038 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007039 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007040 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007041
7042 // Touch Window 2
7043 touchedPoint = {150, 150};
7044 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007045 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7046 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007047
chaviw9eaa22c2020-07-01 16:21:27 -07007048 // Update the transform so rotation is set
7049 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007050 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007051 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7052 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007053}
7054
chaviw9eaa22c2020-07-01 16:21:27 -07007055TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007056 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007057 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007058
7059 // Touch Window 1
7060 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7061 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007062 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007063
7064 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007065 touchedPoints.push_back(PointF{150, 150});
7066 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007067 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007068
chaviw9eaa22c2020-07-01 16:21:27 -07007069 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007070 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007071 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007072
chaviw9eaa22c2020-07-01 16:21:27 -07007073 // Update the transform so rotation is set for Window 2
7074 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007075 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007076 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007077 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007078}
7079
chaviw9eaa22c2020-07-01 16:21:27 -07007080TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007081 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007082 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007083
7084 // Touch Window 1
7085 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7086 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007087 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007088
7089 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007090 touchedPoints.push_back(PointF{150, 150});
7091 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007092
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007093 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007094
7095 // Move both windows
7096 touchedPoints = {{20, 20}, {175, 175}};
7097 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7098 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7099
chaviw9eaa22c2020-07-01 16:21:27 -07007100 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007101
chaviw9eaa22c2020-07-01 16:21:27 -07007102 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007103 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007104 expectedPoints.pop_back();
7105
7106 // Touch Window 2
7107 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007108 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007109 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007110 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007111
7112 // Move both windows
7113 touchedPoints = {{20, 20}, {175, 175}};
7114 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7115 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7116
7117 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007118}
7119
7120TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7121 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007122 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007123
7124 // Touch Window 1
7125 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7126 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007127 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007128
7129 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007130 touchedPoints.push_back(PointF{150, 150});
7131 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007132
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007133 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007134
7135 // Move both windows
7136 touchedPoints = {{20, 20}, {175, 175}};
7137 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7138 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7139
chaviw9eaa22c2020-07-01 16:21:27 -07007140 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007141}
7142
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007143/**
7144 * When one of the windows is slippery, the touch should not slip into the other window with the
7145 * same input channel.
7146 */
7147TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7148 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007149 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007150
7151 // Touch down in window 1
7152 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7153 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7154 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7155
7156 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7157 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7158 // getting generated.
7159 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7160 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7161
7162 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7163}
7164
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007165/**
7166 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7167 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7168 * that the pointer is hovering over may have a different transform.
7169 */
7170TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007171 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007172
7173 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7175 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7176 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007177 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7178 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007179 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7181 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7182 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007183 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7184 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7185 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7186}
7187
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007188class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7189 virtual void SetUp() override {
7190 InputDispatcherTest::SetUp();
7191
Chris Yea209fde2020-07-22 13:54:51 -07007192 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007193 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007194 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7195 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007196 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007197 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007198 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007199
7200 // Set focused application.
7201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7202
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007203 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007204 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007205 mWindow->consumeFocusEvent(true);
7206 }
7207
7208 virtual void TearDown() override {
7209 InputDispatcherTest::TearDown();
7210 mWindow.clear();
7211 }
7212
7213protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007214 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007215 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007216 sp<FakeWindowHandle> mWindow;
7217 static constexpr PointF WINDOW_LOCATION = {20, 20};
7218
7219 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007221 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007222 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007224 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007225 WINDOW_LOCATION));
7226 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007227
7228 sp<FakeWindowHandle> addSpyWindow() {
7229 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007230 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007231 spy->setTrustedOverlay(true);
7232 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007233 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007234 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007235 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007236 return spy;
7237 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007238};
7239
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007240// Send a tap and respond, which should not cause an ANR.
7241TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7242 tapOnWindow();
7243 mWindow->consumeMotionDown();
7244 mWindow->consumeMotionUp();
7245 ASSERT_TRUE(mDispatcher->waitForIdle());
7246 mFakePolicy->assertNotifyAnrWasNotCalled();
7247}
7248
7249// Send a regular key and respond, which should not cause an ANR.
7250TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007252 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7253 ASSERT_TRUE(mDispatcher->waitForIdle());
7254 mFakePolicy->assertNotifyAnrWasNotCalled();
7255}
7256
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007257TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7258 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007259 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007260 mWindow->consumeFocusEvent(false);
7261
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007263 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7264 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007265 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007267 // Key will not go to window because we have no focused window.
7268 // The 'no focused window' ANR timer should start instead.
7269
7270 // Now, the focused application goes away.
7271 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7272 // The key should get dropped and there should be no ANR.
7273
7274 ASSERT_TRUE(mDispatcher->waitForIdle());
7275 mFakePolicy->assertNotifyAnrWasNotCalled();
7276}
7277
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007278// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7280// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007281TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007283 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007284 WINDOW_LOCATION));
7285
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007286 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7287 ASSERT_TRUE(sequenceNum);
7288 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007289 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007290
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007291 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007292 mWindow->consumeMotionEvent(
7293 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007294 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007295 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007296}
7297
7298// Send a key to the app and have the app not respond right away.
7299TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7300 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007302 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7303 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007304 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007305 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007306 ASSERT_TRUE(mDispatcher->waitForIdle());
7307}
7308
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007309// We have a focused application, but no focused window
7310TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007311 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007312 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007313 mWindow->consumeFocusEvent(false);
7314
7315 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007317 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007318 WINDOW_LOCATION));
7319 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7320 mDispatcher->waitForIdle();
7321 mFakePolicy->assertNotifyAnrWasNotCalled();
7322
7323 // Once a focused event arrives, we get an ANR for this application
7324 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7325 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007326 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007327 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007328 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007329 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007330 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007331 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007332 ASSERT_TRUE(mDispatcher->waitForIdle());
7333}
7334
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007335/**
7336 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7337 * there will not be an ANR.
7338 */
7339TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7340 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007341 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007342 mWindow->consumeFocusEvent(false);
7343
7344 KeyEvent event;
7345 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7346 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7347
7348 // Define a valid key down event that is stale (too old).
7349 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007350 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007351 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007352
7353 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7354
7355 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007356 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007357 InputEventInjectionSync::WAIT_FOR_RESULT,
7358 INJECT_EVENT_TIMEOUT, policyFlags);
7359 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7360 << "Injection should fail because the event is stale";
7361
7362 ASSERT_TRUE(mDispatcher->waitForIdle());
7363 mFakePolicy->assertNotifyAnrWasNotCalled();
7364 mWindow->assertNoEvents();
7365}
7366
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007367// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007368// Make sure that we don't notify policy twice about the same ANR.
7369TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007370 const std::chrono::duration appTimeout = 400ms;
7371 mApplication->setDispatchingTimeout(appTimeout);
7372 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7373
Vishnu Nair47074b82020-08-14 11:54:47 -07007374 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007375 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007376 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377
7378 // Once a focused event arrives, we get an ANR for this application
7379 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7380 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007381 const std::chrono::duration eventInjectionTimeout = 100ms;
7382 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007383 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007384 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007385 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7386 /*allowKeyRepeat=*/false);
7387 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7388 << "result=" << ftl::enum_string(result);
7389 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7390 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7391 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7392 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007393
Vishnu Naire4df8752022-09-08 09:17:55 -07007394 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007395 // ANR should not be raised again. It is up to policy to do that if it desires.
7396 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007397
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007398 // If we now get a focused window, the ANR should stop, but the policy handles that via
7399 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007400 ASSERT_TRUE(mDispatcher->waitForIdle());
7401}
7402
7403// We have a focused application, but no focused window
7404TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007405 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007406 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007407 mWindow->consumeFocusEvent(false);
7408
7409 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007410 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007411
Vishnu Naire4df8752022-09-08 09:17:55 -07007412 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7413 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414
7415 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007416 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007417 ASSERT_TRUE(mDispatcher->waitForIdle());
7418 mWindow->assertNoEvents();
7419}
7420
7421/**
7422 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7423 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7424 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7425 * the ANR mechanism should still work.
7426 *
7427 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7428 * DOWN event, while not responding on the second one.
7429 */
7430TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7431 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007432 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007433 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7434 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7435 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007436 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007437
7438 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007439 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007440 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7441 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7442 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007443 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007444
7445 // We have now sent down and up. Let's consume first event and then ANR on the second.
7446 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7447 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007448 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007449}
7450
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007451// A spy window can receive an ANR
7452TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7453 sp<FakeWindowHandle> spy = addSpyWindow();
7454
7455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007456 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007457 WINDOW_LOCATION));
7458 mWindow->consumeMotionDown();
7459
7460 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7461 ASSERT_TRUE(sequenceNum);
7462 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007463 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007464
7465 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007466 spy->consumeMotionEvent(
7467 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007468 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007469 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007470}
7471
7472// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007474TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7475 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007476
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007478 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007479 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007481
7482 // Stuck on the ACTION_UP
7483 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007484 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007485
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007486 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007487 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007488 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7489 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007490
7491 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7492 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007493 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007494 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007495 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007496}
7497
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007498// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007499// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007500TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7501 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007502
7503 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007504 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7505 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007506
7507 mWindow->consumeMotionDown();
7508 // Stuck on the ACTION_UP
7509 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007510 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007511
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007512 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007513 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007514 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7515 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007516
7517 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7518 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007519 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007520 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007521 spy->assertNoEvents();
7522}
7523
7524TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007525 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007526
Prabir Pradhanfb549072023-10-05 19:17:36 +00007527 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007528
7529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007530 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007531 WINDOW_LOCATION));
7532
7533 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7534 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7535 ASSERT_TRUE(consumeSeq);
7536
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007537 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7538 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007539
7540 monitor.finishEvent(*consumeSeq);
7541 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7542
7543 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007544 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007545}
7546
7547// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7548// process events, you don't get an anr. When the window later becomes unresponsive again, you
7549// get an ANR again.
7550// 1. tap -> block on ACTION_UP -> receive ANR
7551// 2. consume all pending events (= queue becomes healthy again)
7552// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7553TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7554 tapOnWindow();
7555
7556 mWindow->consumeMotionDown();
7557 // Block on ACTION_UP
7558 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007559 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007560 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7561 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007562 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007563 mWindow->assertNoEvents();
7564
7565 tapOnWindow();
7566 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007567 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007568 mWindow->consumeMotionUp();
7569
7570 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007571 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007572 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007573 mWindow->assertNoEvents();
7574}
7575
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007576// If a connection remains unresponsive for a while, make sure policy is only notified once about
7577// it.
7578TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007580 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007581 WINDOW_LOCATION));
7582
7583 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007584 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007585 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007586 // 'notifyConnectionUnresponsive' should only be called once per connection
7587 mFakePolicy->assertNotifyAnrWasNotCalled();
7588 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007589 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007590 mWindow->consumeMotionEvent(
7591 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007592 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007593 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007594 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007595 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007596}
7597
7598/**
7599 * 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 -07007600 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007601 *
7602 * Warning!!!
7603 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7604 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007605 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007606 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7607 *
7608 * If that value changes, this test should also change.
7609 */
7610TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7611 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007612 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007613
7614 tapOnWindow();
7615 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7616 ASSERT_TRUE(downSequenceNum);
7617 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7618 ASSERT_TRUE(upSequenceNum);
7619 // Don't finish the events yet, and send a key
7620 // Injection will "succeed" because we will eventually give up and send the key to the focused
7621 // window even if motions are still being processed. But because the injection timeout is short,
7622 // we will receive INJECTION_TIMED_OUT as the result.
7623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007624 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007625 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7626 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007628 // Key will not be sent to the window, yet, because the window is still processing events
7629 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007630 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7631 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7632 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7633 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007634
7635 std::this_thread::sleep_for(500ms);
7636 // if we wait long enough though, dispatcher will give up, and still send the key
7637 // to the focused window, even though we have not yet finished the motion event
7638 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7639 mWindow->finishEvent(*downSequenceNum);
7640 mWindow->finishEvent(*upSequenceNum);
7641}
7642
7643/**
7644 * If a window is processing a motion event, and then a key event comes in, the key event should
7645 * not go to the focused window until the motion is processed.
7646 * If then a new motion comes in, then the pending key event should be going to the currently
7647 * focused window right away.
7648 */
7649TEST_F(InputDispatcherSingleWindowAnr,
7650 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7651 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007652 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007653
7654 tapOnWindow();
7655 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7656 ASSERT_TRUE(downSequenceNum);
7657 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7658 ASSERT_TRUE(upSequenceNum);
7659 // Don't finish the events yet, and send a key
7660 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007662 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7663 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007664 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007665 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7666 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7667 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7668 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007669
7670 // Now tap down again. It should cause the pending key to go to the focused window right away.
7671 tapOnWindow();
7672 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7673 // the other events yet. We can finish events in any order.
7674 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7675 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7676 mWindow->consumeMotionDown();
7677 mWindow->consumeMotionUp();
7678 mWindow->assertNoEvents();
7679}
7680
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007681/**
7682 * Send an event to the app and have the app not respond right away.
7683 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7684 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7685 * At some point, the window becomes responsive again.
7686 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7687 */
7688TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7690 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7691 .build());
7692
7693 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7694 ASSERT_TRUE(sequenceNum);
7695 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7696 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7697
7698 mWindow->finishEvent(*sequenceNum);
7699 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7700 ASSERT_TRUE(mDispatcher->waitForIdle());
7701 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7702
7703 // Now that the window is responsive, let's continue the gesture.
7704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7705 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7706 .build());
7707
7708 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7709 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7710 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7711 .build());
7712
7713 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7714 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7715 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7716 .build());
7717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7718 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7719 .build());
7720 // We already canceled this pointer, so the window shouldn't get any new events.
7721 mWindow->assertNoEvents();
7722
7723 // Start another one.
7724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7725 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7726 .build());
7727 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7728}
7729
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007730class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7731 virtual void SetUp() override {
7732 InputDispatcherTest::SetUp();
7733
Chris Yea209fde2020-07-22 13:54:51 -07007734 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007735 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007736 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7737 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007738 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007739 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007740 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007741
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007742 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7743 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007744 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007745 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007746
7747 // Set focused application.
7748 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007749 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007750
7751 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007752 mDispatcher->onWindowInfosChanged(
7753 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007754 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007755 mFocusedWindow->consumeFocusEvent(true);
7756 }
7757
7758 virtual void TearDown() override {
7759 InputDispatcherTest::TearDown();
7760
7761 mUnfocusedWindow.clear();
7762 mFocusedWindow.clear();
7763 }
7764
7765protected:
Chris Yea209fde2020-07-22 13:54:51 -07007766 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007767 sp<FakeWindowHandle> mUnfocusedWindow;
7768 sp<FakeWindowHandle> mFocusedWindow;
7769 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7770 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7771 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7772
7773 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7774
7775 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7776
7777private:
7778 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007781 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007783 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784 location));
7785 }
7786};
7787
7788// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7789// should be ANR'd first.
7790TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007792 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007793 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007795 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007796 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007797 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007798 // We consumed all events, so no ANR
7799 ASSERT_TRUE(mDispatcher->waitForIdle());
7800 mFakePolicy->assertNotifyAnrWasNotCalled();
7801
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007804 FOCUSED_WINDOW_LOCATION));
7805 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7806 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007807
7808 const std::chrono::duration timeout =
7809 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007810 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007811 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7812 // sequence to make it consistent
7813 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007814 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007815 mFocusedWindow->consumeMotionDown();
7816 // This cancel is generated because the connection was unresponsive
7817 mFocusedWindow->consumeMotionCancel();
7818 mFocusedWindow->assertNoEvents();
7819 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007820 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007821 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7822 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007823 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824}
7825
7826// If we have 2 windows with identical timeouts that are both unresponsive,
7827// it doesn't matter which order they should have ANR.
7828// But we should receive ANR for both.
7829TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7830 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007831 mUnfocusedWindow->setDispatchingTimeout(
7832 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007833 mDispatcher->onWindowInfosChanged(
7834 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007835
7836 tapOnFocusedWindow();
7837 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007838 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007839 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7840 mFocusedWindow->getDispatchingTimeout(
7841 DISPATCHING_TIMEOUT)),
7842 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7843
7844 ASSERT_THAT(anrConnectionTokens,
7845 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7846 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007847
7848 ASSERT_TRUE(mDispatcher->waitForIdle());
7849 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007850
7851 mFocusedWindow->consumeMotionDown();
7852 mFocusedWindow->consumeMotionUp();
7853 mUnfocusedWindow->consumeMotionOutside();
7854
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007855 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7856 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007857
7858 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007859 ASSERT_THAT(responsiveTokens,
7860 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7861 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007862 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007863}
7864
7865// If a window is already not responding, the second tap on the same window should be ignored.
7866// We should also log an error to account for the dropped event (not tested here).
7867// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7868TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7869 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007870 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007871 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007872 // Receive the events, but don't respond
7873 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7874 ASSERT_TRUE(downEventSequenceNum);
7875 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7876 ASSERT_TRUE(upEventSequenceNum);
7877 const std::chrono::duration timeout =
7878 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007879 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007880
7881 // Tap once again
7882 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007883 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007885 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007886 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007887 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888 FOCUSED_WINDOW_LOCATION));
7889 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7890 // valid touch target
7891 mUnfocusedWindow->assertNoEvents();
7892
7893 // Consume the first tap
7894 mFocusedWindow->finishEvent(*downEventSequenceNum);
7895 mFocusedWindow->finishEvent(*upEventSequenceNum);
7896 ASSERT_TRUE(mDispatcher->waitForIdle());
7897 // The second tap did not go to the focused window
7898 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007899 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007900 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7901 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007902 mFakePolicy->assertNotifyAnrWasNotCalled();
7903}
7904
7905// If you tap outside of all windows, there will not be ANR
7906TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007907 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007908 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007909 LOCATION_OUTSIDE_ALL_WINDOWS));
7910 ASSERT_TRUE(mDispatcher->waitForIdle());
7911 mFakePolicy->assertNotifyAnrWasNotCalled();
7912}
7913
7914// Since the focused window is paused, tapping on it should not produce any events
7915TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7916 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007917 mDispatcher->onWindowInfosChanged(
7918 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007919
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007920 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007921 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922 FOCUSED_WINDOW_LOCATION));
7923
7924 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7925 ASSERT_TRUE(mDispatcher->waitForIdle());
7926 // Should not ANR because the window is paused, and touches shouldn't go to it
7927 mFakePolicy->assertNotifyAnrWasNotCalled();
7928
7929 mFocusedWindow->assertNoEvents();
7930 mUnfocusedWindow->assertNoEvents();
7931}
7932
7933/**
7934 * 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 -07007935 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936 * If a different window becomes focused at this time, the key should go to that window instead.
7937 *
7938 * Warning!!!
7939 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7940 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007941 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7943 *
7944 * If that value changes, this test should also change.
7945 */
7946TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7947 // Set a long ANR timeout to prevent it from triggering
7948 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007949 mDispatcher->onWindowInfosChanged(
7950 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951
7952 tapOnUnfocusedWindow();
7953 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7954 ASSERT_TRUE(downSequenceNum);
7955 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7956 ASSERT_TRUE(upSequenceNum);
7957 // Don't finish the events yet, and send a key
7958 // Injection will succeed because we will eventually give up and send the key to the focused
7959 // window even if motions are still being processed.
7960
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007961 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007962 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7963 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007965 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007966 // and the key remains pending, waiting for the touch events to be processed.
7967 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7968 // under the hood.
7969 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7970 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007971
7972 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007973 mFocusedWindow->setFocusable(false);
7974 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007975 mDispatcher->onWindowInfosChanged(
7976 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007977 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007978
7979 // Focus events should precede the key events
7980 mUnfocusedWindow->consumeFocusEvent(true);
7981 mFocusedWindow->consumeFocusEvent(false);
7982
7983 // Finish the tap events, which should unblock dispatcher
7984 mUnfocusedWindow->finishEvent(*downSequenceNum);
7985 mUnfocusedWindow->finishEvent(*upSequenceNum);
7986
7987 // Now that all queues are cleared and no backlog in the connections, the key event
7988 // can finally go to the newly focused "mUnfocusedWindow".
7989 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7990 mFocusedWindow->assertNoEvents();
7991 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007992 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007993}
7994
7995// When the touch stream is split across 2 windows, and one of them does not respond,
7996// then ANR should be raised and the touch should be canceled for the unresponsive window.
7997// The other window should not be affected by that.
7998TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7999 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008000 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8001 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8002 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008003 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008004 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008005
8006 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008007 mDispatcher->notifyMotion(
8008 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8009 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008010
8011 const std::chrono::duration timeout =
8012 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008013 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008014
8015 mUnfocusedWindow->consumeMotionDown();
8016 mFocusedWindow->consumeMotionDown();
8017 // Focused window may or may not receive ACTION_MOVE
8018 // But it should definitely receive ACTION_CANCEL due to the ANR
8019 InputEvent* event;
8020 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8021 ASSERT_TRUE(moveOrCancelSequenceNum);
8022 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8023 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008024 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008025 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8026 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8027 mFocusedWindow->consumeMotionCancel();
8028 } else {
8029 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8030 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008031 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008032 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8033 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008034
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008035 mUnfocusedWindow->assertNoEvents();
8036 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008037 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008038}
8039
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008040/**
8041 * If we have no focused window, and a key comes in, we start the ANR timer.
8042 * The focused application should add a focused window before the timer runs out to prevent ANR.
8043 *
8044 * If the user touches another application during this time, the key should be dropped.
8045 * Next, if a new focused window comes in, without toggling the focused application,
8046 * then no ANR should occur.
8047 *
8048 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8049 * but in some cases the policy may not update the focused application.
8050 */
8051TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8052 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8053 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008054 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8056 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8057 mFocusedWindow->setFocusable(false);
8058
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008059 mDispatcher->onWindowInfosChanged(
8060 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008061 mFocusedWindow->consumeFocusEvent(false);
8062
8063 // Send a key. The ANR timer should start because there is no focused window.
8064 // 'focusedApplication' will get blamed if this timer completes.
8065 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008066 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008067 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8068 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008069 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008071
8072 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8073 // then the injected touches won't cause the focused event to get dropped.
8074 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8075 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8076 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8077 // For this test, it means that the key would get delivered to the window once it becomes
8078 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008079 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008080
8081 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8083 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8084 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008085
8086 // We do not consume the motion right away, because that would require dispatcher to first
8087 // process (== drop) the key event, and by that time, ANR will be raised.
8088 // Set the focused window first.
8089 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008090 mDispatcher->onWindowInfosChanged(
8091 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008092 setFocusedWindow(mFocusedWindow);
8093 mFocusedWindow->consumeFocusEvent(true);
8094 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8095 // to another application. This could be a bug / behaviour in the policy.
8096
8097 mUnfocusedWindow->consumeMotionDown();
8098
8099 ASSERT_TRUE(mDispatcher->waitForIdle());
8100 // Should not ANR because we actually have a focused window. It was just added too slowly.
8101 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8102}
8103
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008104// These tests ensure we cannot send touch events to a window that's positioned behind a window
8105// that has feature NO_INPUT_CHANNEL.
8106// Layout:
8107// Top (closest to user)
8108// mNoInputWindow (above all windows)
8109// mBottomWindow
8110// Bottom (furthest from user)
8111class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8112 virtual void SetUp() override {
8113 InputDispatcherTest::SetUp();
8114
8115 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008116 mNoInputWindow =
8117 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8118 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008119 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008120 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008121 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8122 // It's perfectly valid for this window to not have an associated input channel
8123
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008124 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8125 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008126 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8127
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008128 mDispatcher->onWindowInfosChanged(
8129 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008130 }
8131
8132protected:
8133 std::shared_ptr<FakeApplicationHandle> mApplication;
8134 sp<FakeWindowHandle> mNoInputWindow;
8135 sp<FakeWindowHandle> mBottomWindow;
8136};
8137
8138TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8139 PointF touchedPoint = {10, 10};
8140
Prabir Pradhan678438e2023-04-13 19:32:51 +00008141 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8142 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8143 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008144
8145 mNoInputWindow->assertNoEvents();
8146 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8147 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8148 // and therefore should prevent mBottomWindow from receiving touches
8149 mBottomWindow->assertNoEvents();
8150}
8151
8152/**
8153 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8154 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8155 */
8156TEST_F(InputDispatcherMultiWindowOcclusionTests,
8157 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008158 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8159 "Window with input channel and NO_INPUT_CHANNEL",
8160 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008161
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008162 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008163 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008164 mDispatcher->onWindowInfosChanged(
8165 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008166
8167 PointF touchedPoint = {10, 10};
8168
Prabir Pradhan678438e2023-04-13 19:32:51 +00008169 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8170 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8171 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008172
8173 mNoInputWindow->assertNoEvents();
8174 mBottomWindow->assertNoEvents();
8175}
8176
Vishnu Nair958da932020-08-21 17:12:37 -07008177class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8178protected:
8179 std::shared_ptr<FakeApplicationHandle> mApp;
8180 sp<FakeWindowHandle> mWindow;
8181 sp<FakeWindowHandle> mMirror;
8182
8183 virtual void SetUp() override {
8184 InputDispatcherTest::SetUp();
8185 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008186 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8187 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8188 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008189 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8190 mWindow->setFocusable(true);
8191 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008192 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008193 }
8194};
8195
8196TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8197 // Request focus on a mirrored window
8198 setFocusedWindow(mMirror);
8199
8200 // window gets focused
8201 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008203 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008204 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8205}
8206
8207// A focused & mirrored window remains focused only if the window and its mirror are both
8208// focusable.
8209TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8210 setFocusedWindow(mMirror);
8211
8212 // window gets focused
8213 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008215 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008216 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008218 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008219 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8220
8221 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008222 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008223
8224 // window loses focus since one of the windows associated with the token in not focusable
8225 mWindow->consumeFocusEvent(false);
8226
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008227 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008228 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008229 mWindow->assertNoEvents();
8230}
8231
8232// A focused & mirrored window remains focused until the window and its mirror both become
8233// invisible.
8234TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8235 setFocusedWindow(mMirror);
8236
8237 // window gets focused
8238 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008240 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008241 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008243 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008244 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8245
8246 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008247 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008248
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008250 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008251 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008253 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008254 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8255
8256 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008257 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008258
8259 // window loses focus only after all windows associated with the token become invisible.
8260 mWindow->consumeFocusEvent(false);
8261
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008262 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008263 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008264 mWindow->assertNoEvents();
8265}
8266
8267// A focused & mirrored window remains focused until both windows are removed.
8268TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8269 setFocusedWindow(mMirror);
8270
8271 // window gets focused
8272 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008274 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008275 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008277 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008278 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8279
8280 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008281 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008282
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008284 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008285 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008288 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8289
8290 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008291 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008292 mWindow->consumeFocusEvent(false);
8293
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008294 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008295 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008296 mWindow->assertNoEvents();
8297}
8298
8299// Focus request can be pending until one window becomes visible.
8300TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8301 // Request focus on an invisible mirror.
8302 mWindow->setVisible(false);
8303 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008304 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008305 setFocusedWindow(mMirror);
8306
8307 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008309 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8310 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008311
8312 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008313 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008314
8315 // window gets focused
8316 mWindow->consumeFocusEvent(true);
8317 // window gets the pending key event
8318 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8319}
Prabir Pradhan99987712020-11-10 18:43:05 -08008320
8321class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8322protected:
8323 std::shared_ptr<FakeApplicationHandle> mApp;
8324 sp<FakeWindowHandle> mWindow;
8325 sp<FakeWindowHandle> mSecondWindow;
8326
8327 void SetUp() override {
8328 InputDispatcherTest::SetUp();
8329 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008330 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008331 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008332 mSecondWindow =
8333 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008334 mSecondWindow->setFocusable(true);
8335
8336 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008337 mDispatcher->onWindowInfosChanged(
8338 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008339
8340 setFocusedWindow(mWindow);
8341 mWindow->consumeFocusEvent(true);
8342 }
8343
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008344 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008345 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008346 }
8347
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008348 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8349 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008350 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008351 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8352 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008353 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008354 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008355 }
8356};
8357
8358TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8359 // Ensure that capture cannot be obtained for unfocused windows.
8360 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8361 mFakePolicy->assertSetPointerCaptureNotCalled();
8362 mSecondWindow->assertNoEvents();
8363
8364 // Ensure that capture can be enabled from the focus window.
8365 requestAndVerifyPointerCapture(mWindow, true);
8366
8367 // Ensure that capture cannot be disabled from a window that does not have capture.
8368 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8369 mFakePolicy->assertSetPointerCaptureNotCalled();
8370
8371 // Ensure that capture can be disabled from the window with capture.
8372 requestAndVerifyPointerCapture(mWindow, false);
8373}
8374
8375TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008376 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008377
8378 setFocusedWindow(mSecondWindow);
8379
8380 // Ensure that the capture disabled event was sent first.
8381 mWindow->consumeCaptureEvent(false);
8382 mWindow->consumeFocusEvent(false);
8383 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008384 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008385
8386 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008387 notifyPointerCaptureChanged({});
8388 notifyPointerCaptureChanged(request);
8389 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008390 mWindow->assertNoEvents();
8391 mSecondWindow->assertNoEvents();
8392 mFakePolicy->assertSetPointerCaptureNotCalled();
8393}
8394
8395TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008396 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008397
8398 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008399 notifyPointerCaptureChanged({});
8400 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008401
8402 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008403 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008404 mWindow->consumeCaptureEvent(false);
8405 mWindow->assertNoEvents();
8406}
8407
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008408TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8409 requestAndVerifyPointerCapture(mWindow, true);
8410
8411 // The first window loses focus.
8412 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008413 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008414 mWindow->consumeCaptureEvent(false);
8415
8416 // Request Pointer Capture from the second window before the notification from InputReader
8417 // arrives.
8418 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008419 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008420
8421 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008422 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008423
8424 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008425 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008426
8427 mSecondWindow->consumeFocusEvent(true);
8428 mSecondWindow->consumeCaptureEvent(true);
8429}
8430
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008431TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8432 // App repeatedly enables and disables capture.
8433 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8434 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8435 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8436 mFakePolicy->assertSetPointerCaptureCalled(false);
8437 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8438 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8439
8440 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8441 // first request is now stale, this should do nothing.
8442 notifyPointerCaptureChanged(firstRequest);
8443 mWindow->assertNoEvents();
8444
8445 // InputReader notifies that the second request was enabled.
8446 notifyPointerCaptureChanged(secondRequest);
8447 mWindow->consumeCaptureEvent(true);
8448}
8449
Prabir Pradhan7092e262022-05-03 16:51:09 +00008450TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8451 requestAndVerifyPointerCapture(mWindow, true);
8452
8453 // App toggles pointer capture off and on.
8454 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8455 mFakePolicy->assertSetPointerCaptureCalled(false);
8456
8457 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8458 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8459
8460 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8461 // preceding "disable" request.
8462 notifyPointerCaptureChanged(enableRequest);
8463
8464 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8465 // any notifications.
8466 mWindow->assertNoEvents();
8467}
8468
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008469/**
8470 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8471 * mouse movements don't affect the previous mouse hovering state.
8472 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8473 * HOVER_MOVE events).
8474 */
8475TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8476 // Mouse hover on the window
8477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8479 .build());
8480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8481 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8482 .build());
8483
8484 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8485 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8486
8487 // Start pointer capture
8488 requestAndVerifyPointerCapture(mWindow, true);
8489
8490 // Send some relative mouse movements and receive them in the window.
8491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8493 .build());
8494 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8495 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8496
8497 // Stop pointer capture
8498 requestAndVerifyPointerCapture(mWindow, false);
8499
8500 // Continue hovering on the window
8501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8502 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8503 .build());
8504 mWindow->consumeMotionEvent(
8505 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8506
8507 mWindow->assertNoEvents();
8508}
8509
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008510class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8511protected:
8512 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008513
8514 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8515 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8516
8517 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8518 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8519
8520 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8521 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8522 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8523 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8524 MAXIMUM_OBSCURING_OPACITY);
8525
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008526 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8527 static constexpr gui::Uid APP_B_UID{10002};
8528 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008529
8530 sp<FakeWindowHandle> mTouchWindow;
8531
8532 virtual void SetUp() override {
8533 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008534 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008535 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8536 }
8537
8538 virtual void TearDown() override {
8539 InputDispatcherTest::TearDown();
8540 mTouchWindow.clear();
8541 }
8542
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008543 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008544 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008545 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008546 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008547 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008548 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008549 return window;
8550 }
8551
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008552 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008553 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8554 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008555 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008556 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008557 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008558 return window;
8559 }
8560
8561 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008562 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8563 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8564 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008565 }
8566};
8567
8568TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008569 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008570 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008571 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008572
8573 touch();
8574
8575 mTouchWindow->assertNoEvents();
8576}
8577
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008578TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008579 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8580 const sp<FakeWindowHandle>& w =
8581 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008582 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008583
8584 touch();
8585
8586 mTouchWindow->assertNoEvents();
8587}
8588
8589TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008590 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8591 const sp<FakeWindowHandle>& w =
8592 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008593 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008594
8595 touch();
8596
8597 w->assertNoEvents();
8598}
8599
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008600TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008601 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008602 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008603
8604 touch();
8605
8606 mTouchWindow->consumeAnyMotionDown();
8607}
8608
8609TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008610 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008611 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008612 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008613 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008614
8615 touch({PointF{100, 100}});
8616
8617 mTouchWindow->consumeAnyMotionDown();
8618}
8619
8620TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008621 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008622 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008623 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008624
8625 touch();
8626
8627 mTouchWindow->consumeAnyMotionDown();
8628}
8629
8630TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8631 const sp<FakeWindowHandle>& w =
8632 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008633 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008634
8635 touch();
8636
8637 mTouchWindow->consumeAnyMotionDown();
8638}
8639
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008640TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8641 const sp<FakeWindowHandle>& w =
8642 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008643 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008644
8645 touch();
8646
8647 w->assertNoEvents();
8648}
8649
8650/**
8651 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8652 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8653 * window, the occluding window will still receive ACTION_OUTSIDE event.
8654 */
8655TEST_F(InputDispatcherUntrustedTouchesTest,
8656 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8657 const sp<FakeWindowHandle>& w =
8658 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008659 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008660 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008661
8662 touch();
8663
8664 w->consumeMotionOutside();
8665}
8666
8667TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8668 const sp<FakeWindowHandle>& w =
8669 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008670 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008671 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008672
8673 touch();
8674
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008675 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008676}
8677
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008678TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008679 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008680 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8681 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008682 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008683
8684 touch();
8685
8686 mTouchWindow->consumeAnyMotionDown();
8687}
8688
8689TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8690 const sp<FakeWindowHandle>& w =
8691 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8692 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008693 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008694
8695 touch();
8696
8697 mTouchWindow->consumeAnyMotionDown();
8698}
8699
8700TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008701 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008702 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8703 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008704 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008705
8706 touch();
8707
8708 mTouchWindow->assertNoEvents();
8709}
8710
8711TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8712 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8713 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008714 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8715 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008716 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008717 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8718 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008719 mDispatcher->onWindowInfosChanged(
8720 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008721
8722 touch();
8723
8724 mTouchWindow->assertNoEvents();
8725}
8726
8727TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8728 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8729 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008730 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8731 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008732 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008733 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8734 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008735 mDispatcher->onWindowInfosChanged(
8736 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008737
8738 touch();
8739
8740 mTouchWindow->consumeAnyMotionDown();
8741}
8742
8743TEST_F(InputDispatcherUntrustedTouchesTest,
8744 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8745 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008746 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8747 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008748 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008749 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8750 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged(
8752 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008753
8754 touch();
8755
8756 mTouchWindow->consumeAnyMotionDown();
8757}
8758
8759TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8760 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008761 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8762 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008763 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008764 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8765 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008766 mDispatcher->onWindowInfosChanged(
8767 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008768
8769 touch();
8770
8771 mTouchWindow->assertNoEvents();
8772}
8773
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008774TEST_F(InputDispatcherUntrustedTouchesTest,
8775 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8776 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008777 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8778 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008779 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008780 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8781 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008782 mDispatcher->onWindowInfosChanged(
8783 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008784
8785 touch();
8786
8787 mTouchWindow->assertNoEvents();
8788}
8789
8790TEST_F(InputDispatcherUntrustedTouchesTest,
8791 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8792 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008793 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8794 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008795 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008796 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8797 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008798 mDispatcher->onWindowInfosChanged(
8799 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008800
8801 touch();
8802
8803 mTouchWindow->consumeAnyMotionDown();
8804}
8805
8806TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8807 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008808 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8809 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008810 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008811
8812 touch();
8813
8814 mTouchWindow->consumeAnyMotionDown();
8815}
8816
8817TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8818 const sp<FakeWindowHandle>& w =
8819 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008820 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008821
8822 touch();
8823
8824 mTouchWindow->consumeAnyMotionDown();
8825}
8826
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008827TEST_F(InputDispatcherUntrustedTouchesTest,
8828 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8829 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8830 const sp<FakeWindowHandle>& w =
8831 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008832 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008833
8834 touch();
8835
8836 mTouchWindow->assertNoEvents();
8837}
8838
8839TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8840 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8841 const sp<FakeWindowHandle>& w =
8842 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008843 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008844
8845 touch();
8846
8847 mTouchWindow->consumeAnyMotionDown();
8848}
8849
8850TEST_F(InputDispatcherUntrustedTouchesTest,
8851 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8852 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8853 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008854 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8855 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008856 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008857
8858 touch();
8859
8860 mTouchWindow->consumeAnyMotionDown();
8861}
8862
8863TEST_F(InputDispatcherUntrustedTouchesTest,
8864 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8865 const sp<FakeWindowHandle>& w1 =
8866 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8867 OPACITY_BELOW_THRESHOLD);
8868 const sp<FakeWindowHandle>& w2 =
8869 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8870 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008871 mDispatcher->onWindowInfosChanged(
8872 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008873
8874 touch();
8875
8876 mTouchWindow->assertNoEvents();
8877}
8878
8879/**
8880 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8881 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8882 * (which alone would result in allowing touches) does not affect the blocking behavior.
8883 */
8884TEST_F(InputDispatcherUntrustedTouchesTest,
8885 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8886 const sp<FakeWindowHandle>& wB =
8887 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8888 OPACITY_BELOW_THRESHOLD);
8889 const sp<FakeWindowHandle>& wC =
8890 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8891 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008892 mDispatcher->onWindowInfosChanged(
8893 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008894
8895 touch();
8896
8897 mTouchWindow->assertNoEvents();
8898}
8899
8900/**
8901 * This test is testing that a window from a different UID but with same application token doesn't
8902 * block the touch. Apps can share the application token for close UI collaboration for example.
8903 */
8904TEST_F(InputDispatcherUntrustedTouchesTest,
8905 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8906 const sp<FakeWindowHandle>& w =
8907 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8908 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008909 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008910
8911 touch();
8912
8913 mTouchWindow->consumeAnyMotionDown();
8914}
8915
arthurhungb89ccb02020-12-30 16:19:01 +08008916class InputDispatcherDragTests : public InputDispatcherTest {
8917protected:
8918 std::shared_ptr<FakeApplicationHandle> mApp;
8919 sp<FakeWindowHandle> mWindow;
8920 sp<FakeWindowHandle> mSecondWindow;
8921 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008922 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008923 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8924 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008925
8926 void SetUp() override {
8927 InputDispatcherTest::SetUp();
8928 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008929 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008930 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008931
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008932 mSecondWindow =
8933 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008934 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008935
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008936 mSpyWindow =
8937 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008938 mSpyWindow->setSpy(true);
8939 mSpyWindow->setTrustedOverlay(true);
8940 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8941
arthurhungb89ccb02020-12-30 16:19:01 +08008942 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008943 mDispatcher->onWindowInfosChanged(
8944 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8945 {},
8946 0,
8947 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008948 }
8949
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008950 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8951 switch (fromSource) {
8952 case AINPUT_SOURCE_TOUCHSCREEN:
8953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008954 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008955 ADISPLAY_ID_DEFAULT, {50, 50}))
8956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8957 break;
8958 case AINPUT_SOURCE_STYLUS:
8959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008960 injectMotionEvent(*mDispatcher,
8961 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8962 AINPUT_SOURCE_STYLUS)
8963 .buttonState(
8964 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8965 .pointer(PointerBuilder(0, ToolType::STYLUS)
8966 .x(50)
8967 .y(50))
8968 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008969 break;
8970 case AINPUT_SOURCE_MOUSE:
8971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008972 injectMotionEvent(*mDispatcher,
8973 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8974 AINPUT_SOURCE_MOUSE)
8975 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8976 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8977 ToolType::MOUSE)
8978 .x(50)
8979 .y(50))
8980 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008981 break;
8982 default:
8983 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8984 }
arthurhungb89ccb02020-12-30 16:19:01 +08008985
8986 // Window should receive motion event.
8987 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008988 // Spy window should also receive motion event
8989 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008990 }
8991
8992 // Start performing drag, we will create a drag window and transfer touch to it.
8993 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8994 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008995 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008996 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008997 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008998 }
arthurhungb89ccb02020-12-30 16:19:01 +08008999
9000 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009001 mDragWindow =
9002 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009003 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009004 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9005 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9006 {},
9007 0,
9008 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009009
9010 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009011 bool transferred =
9012 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009013 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009014 if (transferred) {
9015 mWindow->consumeMotionCancel();
9016 mDragWindow->consumeMotionDown();
9017 }
9018 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009019 }
9020};
9021
9022TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009023 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009024
9025 // Move on window.
9026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009027 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009028 ADISPLAY_ID_DEFAULT, {50, 50}))
9029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9030 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9031 mWindow->consumeDragEvent(false, 50, 50);
9032 mSecondWindow->assertNoEvents();
9033
9034 // Move to another window.
9035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009036 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009037 ADISPLAY_ID_DEFAULT, {150, 50}))
9038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9039 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9040 mWindow->consumeDragEvent(true, 150, 50);
9041 mSecondWindow->consumeDragEvent(false, 50, 50);
9042
9043 // Move back to original window.
9044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009045 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009046 ADISPLAY_ID_DEFAULT, {50, 50}))
9047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9048 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9049 mWindow->consumeDragEvent(false, 50, 50);
9050 mSecondWindow->consumeDragEvent(true, -50, 50);
9051
9052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009053 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9054 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9056 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9057 mWindow->assertNoEvents();
9058 mSecondWindow->assertNoEvents();
9059}
9060
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009061TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009062 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009063
9064 // No cancel event after drag start
9065 mSpyWindow->assertNoEvents();
9066
9067 const MotionEvent secondFingerDownEvent =
9068 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009070 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9071 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009072 .build();
9073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009074 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009075 InputEventInjectionSync::WAIT_FOR_RESULT))
9076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9077
9078 // Receives cancel for first pointer after next pointer down
9079 mSpyWindow->consumeMotionCancel();
9080 mSpyWindow->consumeMotionDown();
9081
9082 mSpyWindow->assertNoEvents();
9083}
9084
arthurhungf452d0b2021-01-06 00:19:52 +08009085TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009086 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009087
9088 // Move on window.
9089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009090 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009091 ADISPLAY_ID_DEFAULT, {50, 50}))
9092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9093 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9094 mWindow->consumeDragEvent(false, 50, 50);
9095 mSecondWindow->assertNoEvents();
9096
9097 // Move to another window.
9098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009099 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009100 ADISPLAY_ID_DEFAULT, {150, 50}))
9101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9102 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9103 mWindow->consumeDragEvent(true, 150, 50);
9104 mSecondWindow->consumeDragEvent(false, 50, 50);
9105
9106 // drop to another window.
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009108 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009109 {150, 50}))
9110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9111 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009112 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009113 mWindow->assertNoEvents();
9114 mSecondWindow->assertNoEvents();
9115}
9116
arthurhung6d4bed92021-03-17 11:59:33 +08009117TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009118 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009119
9120 // Move on window and keep button pressed.
9121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009122 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009123 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9124 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009125 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009126 .build()))
9127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9128 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9129 mWindow->consumeDragEvent(false, 50, 50);
9130 mSecondWindow->assertNoEvents();
9131
9132 // Move to another window and release button, expect to drop item.
9133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009134 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009135 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9136 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009137 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009138 .build()))
9139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9140 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9141 mWindow->assertNoEvents();
9142 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009143 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009144
9145 // nothing to the window.
9146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009147 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009148 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9149 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009150 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009151 .build()))
9152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9153 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9154 mWindow->assertNoEvents();
9155 mSecondWindow->assertNoEvents();
9156}
9157
Arthur Hung54745652022-04-20 07:17:41 +00009158TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009159 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009160
9161 // Set second window invisible.
9162 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009163 mDispatcher->onWindowInfosChanged(
9164 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009165
9166 // Move on window.
9167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009168 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009169 ADISPLAY_ID_DEFAULT, {50, 50}))
9170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9171 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9172 mWindow->consumeDragEvent(false, 50, 50);
9173 mSecondWindow->assertNoEvents();
9174
9175 // Move to another window.
9176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009177 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009178 ADISPLAY_ID_DEFAULT, {150, 50}))
9179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9180 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9181 mWindow->consumeDragEvent(true, 150, 50);
9182 mSecondWindow->assertNoEvents();
9183
9184 // drop to another window.
9185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009186 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009187 {150, 50}))
9188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9189 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009190 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009191 mWindow->assertNoEvents();
9192 mSecondWindow->assertNoEvents();
9193}
9194
Arthur Hung54745652022-04-20 07:17:41 +00009195TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009196 // Ensure window could track pointerIds if it didn't support split touch.
9197 mWindow->setPreventSplitting(true);
9198
Arthur Hung54745652022-04-20 07:17:41 +00009199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009200 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009201 {50, 50}))
9202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9203 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9204
9205 const MotionEvent secondFingerDownEvent =
9206 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9207 .displayId(ADISPLAY_ID_DEFAULT)
9208 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009209 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9210 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009211 .build();
9212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009213 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009214 InputEventInjectionSync::WAIT_FOR_RESULT))
9215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009216 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009217
9218 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009219 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009220}
9221
9222TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9223 // First down on second window.
9224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009225 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009226 {150, 50}))
9227 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9228
9229 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9230
9231 // Second down on first window.
9232 const MotionEvent secondFingerDownEvent =
9233 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9234 .displayId(ADISPLAY_ID_DEFAULT)
9235 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009236 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9237 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009238 .build();
9239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009240 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009241 InputEventInjectionSync::WAIT_FOR_RESULT))
9242 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9243 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9244
9245 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009246 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009247
9248 // Move on window.
9249 const MotionEvent secondFingerMoveEvent =
9250 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9251 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009252 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9253 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009254 .build();
9255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009256 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009257 InputEventInjectionSync::WAIT_FOR_RESULT));
9258 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9259 mWindow->consumeDragEvent(false, 50, 50);
9260 mSecondWindow->consumeMotionMove();
9261
9262 // Release the drag pointer should perform drop.
9263 const MotionEvent secondFingerUpEvent =
9264 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9265 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009266 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9267 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009268 .build();
9269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009270 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009271 InputEventInjectionSync::WAIT_FOR_RESULT));
9272 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009273 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009274 mWindow->assertNoEvents();
9275 mSecondWindow->consumeMotionMove();
9276}
9277
Arthur Hung3915c1f2022-05-31 07:17:17 +00009278TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009279 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009280
9281 // Update window of second display.
9282 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009283 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009284 mDispatcher->onWindowInfosChanged(
9285 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9286 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9287 {},
9288 0,
9289 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009290
9291 // Let second display has a touch state.
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009293 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009294 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9295 AINPUT_SOURCE_TOUCHSCREEN)
9296 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009297 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009298 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009299 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009300 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009301 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009302 mDispatcher->onWindowInfosChanged(
9303 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9304 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9305 {},
9306 0,
9307 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009308
9309 // Move on window.
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009312 ADISPLAY_ID_DEFAULT, {50, 50}))
9313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9314 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9315 mWindow->consumeDragEvent(false, 50, 50);
9316 mSecondWindow->assertNoEvents();
9317
9318 // Move to another window.
9319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009320 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009321 ADISPLAY_ID_DEFAULT, {150, 50}))
9322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9323 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9324 mWindow->consumeDragEvent(true, 150, 50);
9325 mSecondWindow->consumeDragEvent(false, 50, 50);
9326
9327 // drop to another window.
9328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009329 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009330 {150, 50}))
9331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9332 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009333 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009334 mWindow->assertNoEvents();
9335 mSecondWindow->assertNoEvents();
9336}
9337
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009338TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9339 startDrag(true, AINPUT_SOURCE_MOUSE);
9340 // Move on window.
9341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009342 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009343 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9344 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009345 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009346 .x(50)
9347 .y(50))
9348 .build()))
9349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9350 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9351 mWindow->consumeDragEvent(false, 50, 50);
9352 mSecondWindow->assertNoEvents();
9353
9354 // Move to another window.
9355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009356 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009357 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9358 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009359 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009360 .x(150)
9361 .y(50))
9362 .build()))
9363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9364 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9365 mWindow->consumeDragEvent(true, 150, 50);
9366 mSecondWindow->consumeDragEvent(false, 50, 50);
9367
9368 // drop to another window.
9369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009370 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009371 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9372 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009373 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009374 .x(150)
9375 .y(50))
9376 .build()))
9377 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9378 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009379 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009380 mWindow->assertNoEvents();
9381 mSecondWindow->assertNoEvents();
9382}
9383
Linnan Li5af92f92023-07-14 14:36:22 +08009384/**
9385 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9386 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9387 */
9388TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9389 // Down on second window
9390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9391 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9392 {150, 50}))
9393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9394
9395 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9396 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9397
9398 // Down on first window
9399 const MotionEvent secondFingerDownEvent =
9400 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9401 .displayId(ADISPLAY_ID_DEFAULT)
9402 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9403 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9404 .build();
9405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9406 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9407 InputEventInjectionSync::WAIT_FOR_RESULT))
9408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9409 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9410 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9411 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9412
9413 // Start drag on first window
9414 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9415
9416 // Trigger cancel
9417 mDispatcher->cancelCurrentTouch();
9418 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9419 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9420 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9421
9422 ASSERT_TRUE(mDispatcher->waitForIdle());
9423 // The D&D finished with nullptr
9424 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9425
9426 // Remove drag window
9427 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9428
9429 // Inject a simple gesture, ensure dispatcher not crashed
9430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9431 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9432 PointF{50, 50}))
9433 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9434 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9435
9436 const MotionEvent moveEvent =
9437 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9438 .displayId(ADISPLAY_ID_DEFAULT)
9439 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9440 .build();
9441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9442 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9443 InputEventInjectionSync::WAIT_FOR_RESULT))
9444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9445 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9446
9447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9448 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9449 {50, 50}))
9450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9451 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9452}
9453
Vishnu Nair062a8672021-09-03 16:07:44 -07009454class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9455
9456TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9457 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009458 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9459 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009460 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009461 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9462 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009463 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009464 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009465 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009466
9467 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009468 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009469 window->assertNoEvents();
9470
Prabir Pradhan678438e2023-04-13 19:32:51 +00009471 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9472 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009473 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9474 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009475 window->assertNoEvents();
9476
9477 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009478 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009479 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009480
Prabir Pradhan678438e2023-04-13 19:32:51 +00009481 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009482 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9483
Prabir Pradhan678438e2023-04-13 19:32:51 +00009484 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9485 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009486 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9487 window->assertNoEvents();
9488}
9489
9490TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9491 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9492 std::make_shared<FakeApplicationHandle>();
9493 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009494 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9495 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009496 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009497 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009498 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009500 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9501 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009502 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009503 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009504 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9505 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009506 mDispatcher->onWindowInfosChanged(
9507 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009508 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009509 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009510
9511 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009512 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009513 window->assertNoEvents();
9514
Prabir Pradhan678438e2023-04-13 19:32:51 +00009515 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9516 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009517 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9518 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009519 window->assertNoEvents();
9520
9521 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009522 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009523 mDispatcher->onWindowInfosChanged(
9524 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009525
Prabir Pradhan678438e2023-04-13 19:32:51 +00009526 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009527 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9528
Prabir Pradhan678438e2023-04-13 19:32:51 +00009529 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9530 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009531 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9532 window->assertNoEvents();
9533}
9534
9535TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9536 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9537 std::make_shared<FakeApplicationHandle>();
9538 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009539 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9540 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009541 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009542 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009543 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009544 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009545 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9546 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009547 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009548 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9550 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009551 mDispatcher->onWindowInfosChanged(
9552 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009553 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009554 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009555
9556 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009557 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009558 window->assertNoEvents();
9559
Prabir Pradhan678438e2023-04-13 19:32:51 +00009560 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9561 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009562 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9563 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009564 window->assertNoEvents();
9565
9566 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009567 mDispatcher->onWindowInfosChanged(
9568 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009569
Prabir Pradhan678438e2023-04-13 19:32:51 +00009570 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009571 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9572
Prabir Pradhan678438e2023-04-13 19:32:51 +00009573 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9574 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009575 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9576 window->assertNoEvents();
9577}
9578
Antonio Kantekf16f2832021-09-28 04:39:20 +00009579class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9580protected:
9581 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009582 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009583 sp<FakeWindowHandle> mWindow;
9584 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009585 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009586
9587 void SetUp() override {
9588 InputDispatcherTest::SetUp();
9589
9590 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009591 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009592 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009593 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009594 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009595 mSecondWindow =
9596 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009597 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009598 mThirdWindow =
9599 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9600 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9601 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009602
9603 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009604 mDispatcher->onWindowInfosChanged(
9605 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9606 {},
9607 0,
9608 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009609 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009610 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009611
Antonio Kantek15beb512022-06-13 22:35:41 +00009612 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009613 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009614 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009615 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9616 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009617 mThirdWindow->assertNoEvents();
9618 }
9619
9620 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9621 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009622 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009623 SECOND_DISPLAY_ID)) {
9624 mWindow->assertNoEvents();
9625 mSecondWindow->assertNoEvents();
9626 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009627 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009628 }
9629
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009630 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009631 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009632 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9633 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009634 mWindow->consumeTouchModeEvent(inTouchMode);
9635 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009636 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009637 }
9638};
9639
Antonio Kantek26defcf2022-02-08 01:12:27 +00009640TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009641 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009642 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9643 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009644 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009645}
9646
Antonio Kantek26defcf2022-02-08 01:12:27 +00009647TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9648 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009649 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009650 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009651 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009652 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009653 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009654 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009655 mWindow->assertNoEvents();
9656 mSecondWindow->assertNoEvents();
9657}
9658
9659TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9660 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009661 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009662 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009663 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009664 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009665 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009666}
9667
Antonio Kantekf16f2832021-09-28 04:39:20 +00009668TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009669 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009670 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9671 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009672 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009673 mWindow->assertNoEvents();
9674 mSecondWindow->assertNoEvents();
9675}
9676
Antonio Kantek15beb512022-06-13 22:35:41 +00009677TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9678 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9679 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9680 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009681 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009682 mWindow->assertNoEvents();
9683 mSecondWindow->assertNoEvents();
9684 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9685}
9686
Antonio Kantek48710e42022-03-24 14:19:30 -07009687TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9688 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9690 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009691 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9692 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9693
9694 // Then remove focus.
9695 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009696 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009697
9698 // Assert that caller can switch touch mode by owning one of the last interacted window.
9699 const WindowInfo& windowInfo = *mWindow->getInfo();
9700 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9701 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009702 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009703}
9704
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009705class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9706public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009707 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009708 std::shared_ptr<FakeApplicationHandle> application =
9709 std::make_shared<FakeApplicationHandle>();
9710 std::string name = "Fake Spy ";
9711 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009712 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9713 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009714 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009715 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009716 return spy;
9717 }
9718
9719 sp<FakeWindowHandle> createForeground() {
9720 std::shared_ptr<FakeApplicationHandle> application =
9721 std::make_shared<FakeApplicationHandle>();
9722 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009723 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9724 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009725 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009726 return window;
9727 }
9728
9729private:
9730 int mSpyCount{0};
9731};
9732
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009733using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009734/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009735 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9736 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009737TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009738 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009739 ScopedSilentDeath _silentDeath;
9740
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009741 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009742 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009743 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009744 ".* not a trusted overlay");
9745}
9746
9747/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009748 * Input injection into a display with a spy window but no foreground windows should succeed.
9749 */
9750TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009751 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009752 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009753
9754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9757 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9758}
9759
9760/**
9761 * Verify the order in which different input windows receive events. The touched foreground window
9762 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9763 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9764 * receive events before ones belows it.
9765 *
9766 * Here, we set up a scenario with four windows in the following Z order from the top:
9767 * spy1, spy2, window, spy3.
9768 * We then inject an event and verify that the foreground "window" receives it first, followed by
9769 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9770 * window.
9771 */
9772TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9773 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009774 auto spy1 = createSpy();
9775 auto spy2 = createSpy();
9776 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009777 mDispatcher->onWindowInfosChanged(
9778 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009779 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9780 const size_t numChannels = channels.size();
9781
Michael Wright8e9a8562022-02-09 13:44:29 +00009782 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009783 if (!epollFd.ok()) {
9784 FAIL() << "Failed to create epoll fd";
9785 }
9786
9787 for (size_t i = 0; i < numChannels; i++) {
9788 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9789 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9790 FAIL() << "Failed to add fd to epoll";
9791 }
9792 }
9793
9794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009795 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9797
9798 std::vector<size_t> eventOrder;
9799 std::vector<struct epoll_event> events(numChannels);
9800 for (;;) {
9801 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9802 (100ms).count());
9803 if (nFds < 0) {
9804 FAIL() << "Failed to call epoll_wait";
9805 }
9806 if (nFds == 0) {
9807 break; // epoll_wait timed out
9808 }
9809 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009810 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009811 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009812 channels[i]->consumeMotionDown();
9813 }
9814 }
9815
9816 // Verify the order in which the events were received.
9817 EXPECT_EQ(3u, eventOrder.size());
9818 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9819 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9820 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9821}
9822
9823/**
9824 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9825 */
9826TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9827 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009828 auto spy = createSpy();
9829 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009830 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009831
9832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009833 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9835 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9836 spy->assertNoEvents();
9837}
9838
9839/**
9840 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9841 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9842 * to the window.
9843 */
9844TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9845 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009846 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009847 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009848 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009849
9850 // Inject an event outside the spy window's touchable region.
9851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9854 window->consumeMotionDown();
9855 spy->assertNoEvents();
9856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009857 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9859 window->consumeMotionUp();
9860 spy->assertNoEvents();
9861
9862 // Inject an event inside the spy window's touchable region.
9863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009864 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009865 {5, 10}))
9866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9867 window->consumeMotionDown();
9868 spy->consumeMotionDown();
9869}
9870
9871/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009872 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009873 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009874 */
9875TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9876 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009877 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009878 auto spy = createSpy();
9879 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009880 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009881 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009882 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009883
9884 // Inject an event outside the spy window's frame and touchable region.
9885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009886 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009887 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9889 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009890 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009891}
9892
9893/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009894 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9895 * pointers that are down within its bounds.
9896 */
9897TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9898 auto windowLeft = createForeground();
9899 windowLeft->setFrame({0, 0, 100, 200});
9900 auto windowRight = createForeground();
9901 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009902 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009903 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009904 mDispatcher->onWindowInfosChanged(
9905 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009906
9907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009908 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009909 {50, 50}))
9910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9911 windowLeft->consumeMotionDown();
9912 spy->consumeMotionDown();
9913
9914 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009915 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009916 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009917 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9918 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009919 .build();
9920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009921 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009922 InputEventInjectionSync::WAIT_FOR_RESULT))
9923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9924 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009925 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009926}
9927
9928/**
9929 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9930 * the spy should receive the second pointer with ACTION_DOWN.
9931 */
9932TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9933 auto window = createForeground();
9934 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009935 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009936 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009937 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009938
9939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009940 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009941 {50, 50}))
9942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9943 window->consumeMotionDown();
9944 spyRight->assertNoEvents();
9945
9946 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009947 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009948 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009949 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9950 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009951 .build();
9952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009953 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009954 InputEventInjectionSync::WAIT_FOR_RESULT))
9955 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009956 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009957 spyRight->consumeMotionDown();
9958}
9959
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009960/**
9961 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9962 * windows should be allowed to control split touch.
9963 */
9964TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009965 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009966 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009967 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009968 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009969
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009970 auto window = createForeground();
9971 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009972
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009973 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009974
9975 // First finger down, no window touched.
9976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009977 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009978 {100, 200}))
9979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9980 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9981 window->assertNoEvents();
9982
9983 // Second finger down on window, the window should receive touch down.
9984 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009985 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009986 .displayId(ADISPLAY_ID_DEFAULT)
9987 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009988 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9989 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009990 .build();
9991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009992 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009993 InputEventInjectionSync::WAIT_FOR_RESULT))
9994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9995
9996 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009997 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009998}
9999
10000/**
10001 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10002 * do not receive key events.
10003 */
10004TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010005 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010006 spy->setFocusable(false);
10007
10008 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010009 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010010 setFocusedWindow(window);
10011 window->consumeFocusEvent(true);
10012
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010014 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10015 window->consumeKeyDown(ADISPLAY_ID_NONE);
10016
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010018 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10019 window->consumeKeyUp(ADISPLAY_ID_NONE);
10020
10021 spy->assertNoEvents();
10022}
10023
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010024using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10025
10026/**
10027 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10028 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10029 */
10030TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10031 auto window = createForeground();
10032 auto spy1 = createSpy();
10033 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010034 mDispatcher->onWindowInfosChanged(
10035 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010036
10037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10040 window->consumeMotionDown();
10041 spy1->consumeMotionDown();
10042 spy2->consumeMotionDown();
10043
10044 // Pilfer pointers from the second spy window.
10045 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10046 spy2->assertNoEvents();
10047 spy1->consumeMotionCancel();
10048 window->consumeMotionCancel();
10049
10050 // The rest of the gesture should only be sent to the second spy window.
10051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010052 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010053 ADISPLAY_ID_DEFAULT))
10054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10055 spy2->consumeMotionMove();
10056 spy1->assertNoEvents();
10057 window->assertNoEvents();
10058}
10059
10060/**
10061 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10062 * in the middle of the gesture.
10063 */
10064TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10065 auto window = createForeground();
10066 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010067 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010068
10069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010070 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10072 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10073 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10074
10075 window->releaseChannel();
10076
10077 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10078
10079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010080 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10082 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10083}
10084
10085/**
10086 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10087 * the spy, but not to any other windows.
10088 */
10089TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10090 auto spy = createSpy();
10091 auto window = createForeground();
10092
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010093 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010094
10095 // First finger down on the window and the spy.
10096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010097 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010098 {100, 200}))
10099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10100 spy->consumeMotionDown();
10101 window->consumeMotionDown();
10102
10103 // Spy window pilfers the pointers.
10104 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10105 window->consumeMotionCancel();
10106
10107 // Second finger down on the window and spy, but the window should not receive the pointer down.
10108 const MotionEvent secondFingerDownEvent =
10109 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10110 .displayId(ADISPLAY_ID_DEFAULT)
10111 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010112 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10113 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010114 .build();
10115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010116 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010117 InputEventInjectionSync::WAIT_FOR_RESULT))
10118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10119
Harry Cutts33476232023-01-30 19:57:29 +000010120 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010121
10122 // Third finger goes down outside all windows, so injection should fail.
10123 const MotionEvent thirdFingerDownEvent =
10124 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10125 .displayId(ADISPLAY_ID_DEFAULT)
10126 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010127 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10128 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10129 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010130 .build();
10131 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010132 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010133 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010134 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010135
10136 spy->assertNoEvents();
10137 window->assertNoEvents();
10138}
10139
10140/**
10141 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10142 */
10143TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10144 auto spy = createSpy();
10145 spy->setFrame(Rect(0, 0, 100, 100));
10146 auto window = createForeground();
10147 window->setFrame(Rect(0, 0, 200, 200));
10148
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010149 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010150
10151 // First finger down on the window only
10152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010153 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010154 {150, 150}))
10155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10156 window->consumeMotionDown();
10157
10158 // Second finger down on the spy and window
10159 const MotionEvent secondFingerDownEvent =
10160 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10161 .displayId(ADISPLAY_ID_DEFAULT)
10162 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010163 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10164 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010165 .build();
10166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010167 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010168 InputEventInjectionSync::WAIT_FOR_RESULT))
10169 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10170 spy->consumeMotionDown();
10171 window->consumeMotionPointerDown(1);
10172
10173 // Third finger down on the spy and window
10174 const MotionEvent thirdFingerDownEvent =
10175 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10176 .displayId(ADISPLAY_ID_DEFAULT)
10177 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010178 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10179 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10180 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010181 .build();
10182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010183 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010184 InputEventInjectionSync::WAIT_FOR_RESULT))
10185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10186 spy->consumeMotionPointerDown(1);
10187 window->consumeMotionPointerDown(2);
10188
10189 // Spy window pilfers the pointers.
10190 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010191 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10192 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010193
10194 spy->assertNoEvents();
10195 window->assertNoEvents();
10196}
10197
10198/**
10199 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10200 * other windows should be canceled. If this results in the cancellation of all pointers for some
10201 * window, then that window should receive ACTION_CANCEL.
10202 */
10203TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10204 auto spy = createSpy();
10205 spy->setFrame(Rect(0, 0, 100, 100));
10206 auto window = createForeground();
10207 window->setFrame(Rect(0, 0, 200, 200));
10208
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010209 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010210
10211 // First finger down on both spy and window
10212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010213 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010214 {10, 10}))
10215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10216 window->consumeMotionDown();
10217 spy->consumeMotionDown();
10218
10219 // Second finger down on the spy and window
10220 const MotionEvent secondFingerDownEvent =
10221 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10222 .displayId(ADISPLAY_ID_DEFAULT)
10223 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010224 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10225 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010226 .build();
10227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010228 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010229 InputEventInjectionSync::WAIT_FOR_RESULT))
10230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10231 spy->consumeMotionPointerDown(1);
10232 window->consumeMotionPointerDown(1);
10233
10234 // Spy window pilfers the pointers.
10235 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10236 window->consumeMotionCancel();
10237
10238 spy->assertNoEvents();
10239 window->assertNoEvents();
10240}
10241
10242/**
10243 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10244 * be sent to other windows
10245 */
10246TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10247 auto spy = createSpy();
10248 spy->setFrame(Rect(0, 0, 100, 100));
10249 auto window = createForeground();
10250 window->setFrame(Rect(0, 0, 200, 200));
10251
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010252 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010253
10254 // First finger down on both window and spy
10255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010256 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010257 {10, 10}))
10258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10259 window->consumeMotionDown();
10260 spy->consumeMotionDown();
10261
10262 // Spy window pilfers the pointers.
10263 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10264 window->consumeMotionCancel();
10265
10266 // Second finger down on the window only
10267 const MotionEvent secondFingerDownEvent =
10268 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10269 .displayId(ADISPLAY_ID_DEFAULT)
10270 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010271 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10272 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010273 .build();
10274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010275 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010276 InputEventInjectionSync::WAIT_FOR_RESULT))
10277 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10278 window->consumeMotionDown();
10279 window->assertNoEvents();
10280
10281 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10282 spy->consumeMotionMove();
10283 spy->assertNoEvents();
10284}
10285
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010286/**
10287 * A window on the left and a window on the right. Also, a spy window that's above all of the
10288 * windows, and spanning both left and right windows.
10289 * Send simultaneous motion streams from two different devices, one to the left window, and another
10290 * to the right window.
10291 * Pilfer from spy window.
10292 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10293 */
10294TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10295 sp<FakeWindowHandle> spy = createSpy();
10296 spy->setFrame(Rect(0, 0, 200, 200));
10297 sp<FakeWindowHandle> leftWindow = createForeground();
10298 leftWindow->setFrame(Rect(0, 0, 100, 100));
10299
10300 sp<FakeWindowHandle> rightWindow = createForeground();
10301 rightWindow->setFrame(Rect(100, 0, 200, 100));
10302
10303 constexpr int32_t stylusDeviceId = 1;
10304 constexpr int32_t touchDeviceId = 2;
10305
10306 mDispatcher->onWindowInfosChanged(
10307 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10308
10309 // Stylus down on left window and spy
10310 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10311 .deviceId(stylusDeviceId)
10312 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10313 .build());
10314 leftWindow->consumeMotionEvent(
10315 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10316 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10317
10318 // Finger down on right window and spy - but spy already has stylus
10319 mDispatcher->notifyMotion(
10320 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10321 .deviceId(touchDeviceId)
10322 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10323 .build());
10324 rightWindow->consumeMotionEvent(
10325 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10326 leftWindow->consumeMotionEvent(
10327 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10328 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10329 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10330
10331 // Act: pilfer from spy. Spy is currently receiving touch events.
10332 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10333 rightWindow->consumeMotionEvent(
10334 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10335
10336 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10337 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10338 .deviceId(stylusDeviceId)
10339 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10340 .build());
10341 mDispatcher->notifyMotion(
10342 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10343 .deviceId(touchDeviceId)
10344 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10345 .build());
10346 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10347
10348 spy->assertNoEvents();
10349 leftWindow->assertNoEvents();
10350 rightWindow->assertNoEvents();
10351}
10352
Prabir Pradhand65552b2021-10-07 11:23:50 -070010353class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10354public:
10355 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10356 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10357 std::make_shared<FakeApplicationHandle>();
10358 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010359 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10360 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010361 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010362 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010363 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010364 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010365 overlay->setTrustedOverlay(true);
10366
10367 std::shared_ptr<FakeApplicationHandle> application =
10368 std::make_shared<FakeApplicationHandle>();
10369 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010370 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10371 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010372 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010373 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010374
10375 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010376 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010377 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010378 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010379 return {std::move(overlay), std::move(window)};
10380 }
10381
10382 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010383 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010384 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010385 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010386 }
10387
10388 void sendStylusEvent(int32_t action) {
10389 NotifyMotionArgs motionArgs =
10390 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10391 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010392 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010393 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010394 }
10395};
10396
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010397using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10398
10399TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010400 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010401 ScopedSilentDeath _silentDeath;
10402
Prabir Pradhand65552b2021-10-07 11:23:50 -070010403 auto [overlay, window] = setupStylusOverlayScenario();
10404 overlay->setTrustedOverlay(false);
10405 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010406 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10407 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010408 ".* not a trusted overlay");
10409}
10410
10411TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10412 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010413 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010414
10415 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10416 overlay->consumeMotionDown();
10417 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10418 overlay->consumeMotionUp();
10419
10420 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10421 window->consumeMotionDown();
10422 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10423 window->consumeMotionUp();
10424
10425 overlay->assertNoEvents();
10426 window->assertNoEvents();
10427}
10428
10429TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10430 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010431 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010432 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010433
10434 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10435 overlay->consumeMotionDown();
10436 window->consumeMotionDown();
10437 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10438 overlay->consumeMotionUp();
10439 window->consumeMotionUp();
10440
10441 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10442 window->consumeMotionDown();
10443 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10444 window->consumeMotionUp();
10445
10446 overlay->assertNoEvents();
10447 window->assertNoEvents();
10448}
10449
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010450/**
10451 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10452 * The scenario is as follows:
10453 * - The stylus interceptor overlay is configured as a spy window.
10454 * - The stylus interceptor spy receives the start of a new stylus gesture.
10455 * - It pilfers pointers and then configures itself to no longer be a spy.
10456 * - The stylus interceptor continues to receive the rest of the gesture.
10457 */
10458TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10459 auto [overlay, window] = setupStylusOverlayScenario();
10460 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010461 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010462
10463 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10464 overlay->consumeMotionDown();
10465 window->consumeMotionDown();
10466
10467 // The interceptor pilfers the pointers.
10468 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10469 window->consumeMotionCancel();
10470
10471 // The interceptor configures itself so that it is no longer a spy.
10472 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010473 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010474
10475 // It continues to receive the rest of the stylus gesture.
10476 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10477 overlay->consumeMotionMove();
10478 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10479 overlay->consumeMotionUp();
10480
10481 window->assertNoEvents();
10482}
10483
Prabir Pradhan5735a322022-04-11 17:23:34 +000010484struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010485 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010486 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010487 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10488 std::unique_ptr<InputDispatcher>& mDispatcher;
10489
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010490 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010491 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10492
10493 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010494 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010495 ADISPLAY_ID_DEFAULT, {100, 200},
10496 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10497 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10498 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10499 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10500 }
10501
10502 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010503 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010504 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010505 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010506 mPolicyFlags);
10507 }
10508
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010509 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010510 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10511 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010512 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10513 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010514 window->setOwnerInfo(mPid, mUid);
10515 return window;
10516 }
10517};
10518
10519using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10520
10521TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010522 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010523 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010524 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010525
10526 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10527 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10528 window->consumeMotionDown();
10529
10530 setFocusedWindow(window);
10531 window->consumeFocusEvent(true);
10532
10533 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10534 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10535 window->consumeKeyDown(ADISPLAY_ID_NONE);
10536}
10537
10538TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010539 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010540 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010541 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010542
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010543 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010544 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10545 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10546
10547 setFocusedWindow(window);
10548 window->consumeFocusEvent(true);
10549
10550 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10551 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10552 window->assertNoEvents();
10553}
10554
10555TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010556 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010557 auto window = owner.createWindow("Owned window");
10558 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010559 spy->setSpy(true);
10560 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010561 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010562
10563 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10564 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10565 spy->consumeMotionDown();
10566 window->consumeMotionDown();
10567}
10568
10569TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010570 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010571 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010572
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010573 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010574 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010575 randosSpy->setSpy(true);
10576 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010577 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010578
10579 // The event is targeted at owner's window, so injection should succeed, but the spy should
10580 // not receive the event.
10581 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10582 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10583 randosSpy->assertNoEvents();
10584 window->consumeMotionDown();
10585}
10586
10587TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010588 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010589 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010590
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010591 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010592 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010593 randosSpy->setSpy(true);
10594 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010595 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010596
10597 // A user that has injection permission can inject into any window.
10598 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010599 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010600 ADISPLAY_ID_DEFAULT));
10601 randosSpy->consumeMotionDown();
10602 window->consumeMotionDown();
10603
10604 setFocusedWindow(randosSpy);
10605 randosSpy->consumeFocusEvent(true);
10606
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010607 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010608 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10609 window->assertNoEvents();
10610}
10611
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010612TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010613 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010614 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010615
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010616 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010617 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010618 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10619 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010620 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010621
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010622 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010623 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10624 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10625 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010626 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010627}
10628
Garfield Tane84e6f92019-08-29 17:28:41 -070010629} // namespace android::inputdispatcher