blob: 34323c33c22a2d802b16d90ff1d6cf14eae325dc [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
Prabir Pradhan453ae732023-10-13 14:30:14 +00004685// Same as above, but while the window is being mirrored.
4686TEST_F(InputDispatcherDisplayProjectionTest,
4687 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4688 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4689
4690 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4691 ui::Transform secondDisplayTransform;
4692 secondDisplayTransform.set(matrix);
4693 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4694
4695 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4696 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4697 addWindow(secondWindowClone);
4698
4699 // Send hover move to the second window, and ensure it shows up as hover enter.
4700 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4701 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4702 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4703 WithCoords(100, 80), WithRawCoords(300, 880)));
4704
4705 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4706 // display.
4707 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4708 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4709 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4710 WithRawCoords(300, 880)));
4711 secondWindow->consumeMotionEvent(
4712 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4713 secondWindow->assertNoEvents();
4714 firstWindow->assertNoEvents();
4715}
4716
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004717TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4718 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4719
4720 // Send hover enter to second window
4721 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4722 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4723 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4724 WithCoords(100, 80), WithRawCoords(300, 880)));
4725
4726 mDispatcher->cancelCurrentTouch();
4727
4728 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4729 WithRawCoords(300, 880)));
4730 secondWindow->assertNoEvents();
4731 firstWindow->assertNoEvents();
4732}
4733
Prabir Pradhan453ae732023-10-13 14:30:14 +00004734// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004735TEST_F(InputDispatcherDisplayProjectionTest,
4736 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4737 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4738
4739 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4740 ui::Transform secondDisplayTransform;
4741 secondDisplayTransform.set(matrix);
4742 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4743
4744 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4745 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4746 addWindow(secondWindowClone);
4747
4748 // Send hover enter to second window
4749 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4750 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4751 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4752 WithCoords(100, 80), WithRawCoords(300, 880),
4753 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4754
4755 mDispatcher->cancelCurrentTouch();
4756
4757 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4758 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4759 WithRawCoords(300, 880),
4760 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4761 secondWindow->assertNoEvents();
4762 firstWindow->assertNoEvents();
4763}
4764
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004765/** Ensure consistent behavior of InputDispatcher in all orientations. */
4766class InputDispatcherDisplayOrientationFixture
4767 : public InputDispatcherDisplayProjectionTest,
4768 public ::testing::WithParamInterface<ui::Rotation> {};
4769
4770// This test verifies the touchable region of a window for all rotations of the display by tapping
4771// in different locations on the display, specifically points close to the four corners of a
4772// window.
4773TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4774 constexpr static int32_t displayWidth = 400;
4775 constexpr static int32_t displayHeight = 800;
4776
4777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4778
4779 const auto rotation = GetParam();
4780
4781 // Set up the display with the specified rotation.
4782 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4783 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4784 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4785 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4786 logicalDisplayWidth, logicalDisplayHeight);
4787 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4788
4789 // Create a window with its bounds determined in the logical display.
4790 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4791 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4792 sp<FakeWindowHandle> window =
4793 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4794 window->setFrame(frameInDisplay, displayTransform);
4795 addWindow(window);
4796
4797 // The following points in logical display space should be inside the window.
4798 static const std::array<vec2, 4> insidePoints{
4799 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4800 for (const auto pointInsideWindow : insidePoints) {
4801 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4802 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004803 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4804 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4805 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004806 window->consumeMotionDown();
4807
Prabir Pradhan678438e2023-04-13 19:32:51 +00004808 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4809 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4810 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004811 window->consumeMotionUp();
4812 }
4813
4814 // The following points in logical display space should be outside the window.
4815 static const std::array<vec2, 5> outsidePoints{
4816 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4817 for (const auto pointOutsideWindow : outsidePoints) {
4818 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4819 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004820 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4821 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4822 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004823
Prabir Pradhan678438e2023-04-13 19:32:51 +00004824 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4825 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4826 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004827 }
4828 window->assertNoEvents();
4829}
4830
4831// Run the precision tests for all rotations.
4832INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4833 InputDispatcherDisplayOrientationFixture,
4834 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4835 ui::ROTATION_270),
4836 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4837 return ftl::enum_string(testParamInfo.param);
4838 });
4839
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004840using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4841 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004842
4843class TransferTouchFixture : public InputDispatcherTest,
4844 public ::testing::WithParamInterface<TransferFunction> {};
4845
4846TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004848
4849 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004850 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004851 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4852 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004853 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004854 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004855 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4856 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004857 sp<FakeWindowHandle> wallpaper =
4858 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4859 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004860 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004861 mDispatcher->onWindowInfosChanged(
4862 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004863
4864 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004865 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4866 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004867
Svet Ganov5d3bc372020-01-26 23:11:07 -08004868 // Only the first window should get the down event
4869 firstWindow->consumeMotionDown();
4870 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004871 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004872
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004873 // Transfer touch to the second window
4874 TransferFunction f = GetParam();
4875 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4876 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004877 // The first window gets cancel and the second gets down
4878 firstWindow->consumeMotionCancel();
4879 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004880 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004881
4882 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004883 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4884 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004885 // The first window gets no events and the second gets up
4886 firstWindow->assertNoEvents();
4887 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004888 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004889}
4890
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004891/**
4892 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4893 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4894 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4895 * natural to the user.
4896 * In this test, we are sending a pointer to both spy window and first window. We then try to
4897 * transfer touch to the second window. The dispatcher should identify the first window as the
4898 * one that should lose the gesture, and therefore the action should be to move the gesture from
4899 * the first window to the second.
4900 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4901 * the other API, as well.
4902 */
4903TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4905
4906 // Create a couple of windows + a spy window
4907 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004908 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004909 spyWindow->setTrustedOverlay(true);
4910 spyWindow->setSpy(true);
4911 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004912 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004913 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004914 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004915
4916 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004917 mDispatcher->onWindowInfosChanged(
4918 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004919
4920 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004921 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4922 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004923 // Only the first window and spy should get the down event
4924 spyWindow->consumeMotionDown();
4925 firstWindow->consumeMotionDown();
4926
4927 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4928 // if f === 'transferTouch'.
4929 TransferFunction f = GetParam();
4930 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4931 ASSERT_TRUE(success);
4932 // The first window gets cancel and the second gets down
4933 firstWindow->consumeMotionCancel();
4934 secondWindow->consumeMotionDown();
4935
4936 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4938 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004939 // The first window gets no events and the second+spy get up
4940 firstWindow->assertNoEvents();
4941 spyWindow->consumeMotionUp();
4942 secondWindow->consumeMotionUp();
4943}
4944
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004945TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004946 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004947
4948 PointF touchPoint = {10, 10};
4949
4950 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004951 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004952 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4953 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004954 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004955 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004956 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4957 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004958 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004959
4960 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004961 mDispatcher->onWindowInfosChanged(
4962 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004963
4964 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004965 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4966 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4967 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004968 // Only the first window should get the down event
4969 firstWindow->consumeMotionDown();
4970 secondWindow->assertNoEvents();
4971
4972 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004973 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4974 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004975 // Only the first window should get the pointer down event
4976 firstWindow->consumeMotionPointerDown(1);
4977 secondWindow->assertNoEvents();
4978
4979 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004980 TransferFunction f = GetParam();
4981 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4982 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004983 // The first window gets cancel and the second gets down and pointer down
4984 firstWindow->consumeMotionCancel();
4985 secondWindow->consumeMotionDown();
4986 secondWindow->consumeMotionPointerDown(1);
4987
4988 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004989 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4990 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004991 // The first window gets nothing and the second gets pointer up
4992 firstWindow->assertNoEvents();
4993 secondWindow->consumeMotionPointerUp(1);
4994
4995 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004996 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4997 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004998 // The first window gets nothing and the second gets up
4999 firstWindow->assertNoEvents();
5000 secondWindow->consumeMotionUp();
5001}
5002
Arthur Hungc539dbb2022-12-08 07:45:36 +00005003TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5005
5006 // Create a couple of windows
5007 sp<FakeWindowHandle> firstWindow =
5008 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5009 ADISPLAY_ID_DEFAULT);
5010 firstWindow->setDupTouchToWallpaper(true);
5011 sp<FakeWindowHandle> secondWindow =
5012 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5013 ADISPLAY_ID_DEFAULT);
5014 secondWindow->setDupTouchToWallpaper(true);
5015
5016 sp<FakeWindowHandle> wallpaper1 =
5017 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5018 wallpaper1->setIsWallpaper(true);
5019
5020 sp<FakeWindowHandle> wallpaper2 =
5021 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5022 wallpaper2->setIsWallpaper(true);
5023 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005024 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5025 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5026 {},
5027 0,
5028 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005029
5030 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005031 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5032 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005033
5034 // Only the first window should get the down event
5035 firstWindow->consumeMotionDown();
5036 secondWindow->assertNoEvents();
5037 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5038 wallpaper2->assertNoEvents();
5039
5040 // Transfer touch focus to the second window
5041 TransferFunction f = GetParam();
5042 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5043 ASSERT_TRUE(success);
5044
5045 // The first window gets cancel and the second gets down
5046 firstWindow->consumeMotionCancel();
5047 secondWindow->consumeMotionDown();
5048 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5049 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5050
5051 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005052 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5053 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005054 // The first window gets no events and the second gets up
5055 firstWindow->assertNoEvents();
5056 secondWindow->consumeMotionUp();
5057 wallpaper1->assertNoEvents();
5058 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5059}
5060
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005061// For the cases of single pointer touch and two pointers non-split touch, the api's
5062// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5063// for the case where there are multiple pointers split across several windows.
5064INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5065 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005066 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5067 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005068 return dispatcher->transferTouch(destChannelToken,
5069 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005070 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005071 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5072 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005073 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005074 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005075 }));
5076
Svet Ganov5d3bc372020-01-26 23:11:07 -08005077TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005079
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005080 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005081 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5082 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005083 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005084
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005085 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005086 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5087 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005088 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005089
5090 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005091 mDispatcher->onWindowInfosChanged(
5092 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005093
5094 PointF pointInFirst = {300, 200};
5095 PointF pointInSecond = {300, 600};
5096
5097 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005098 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5099 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5100 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005101 // Only the first window should get the down event
5102 firstWindow->consumeMotionDown();
5103 secondWindow->assertNoEvents();
5104
5105 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005106 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5107 ADISPLAY_ID_DEFAULT,
5108 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005109 // The first window gets a move and the second a down
5110 firstWindow->consumeMotionMove();
5111 secondWindow->consumeMotionDown();
5112
5113 // Transfer touch focus to the second window
5114 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5115 // The first window gets cancel and the new gets pointer down (it already saw down)
5116 firstWindow->consumeMotionCancel();
5117 secondWindow->consumeMotionPointerDown(1);
5118
5119 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005120 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5121 ADISPLAY_ID_DEFAULT,
5122 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005123 // The first window gets nothing and the second gets pointer up
5124 firstWindow->assertNoEvents();
5125 secondWindow->consumeMotionPointerUp(1);
5126
5127 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005128 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5129 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005130 // The first window gets nothing and the second gets up
5131 firstWindow->assertNoEvents();
5132 secondWindow->consumeMotionUp();
5133}
5134
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005135// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5136// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5137// touch is not supported, so the touch should continue on those windows and the transferred-to
5138// window should get nothing.
5139TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5141
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005142 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005143 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5144 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005145 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005146
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005147 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005148 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5149 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005150 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005151
5152 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005153 mDispatcher->onWindowInfosChanged(
5154 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005155
5156 PointF pointInFirst = {300, 200};
5157 PointF pointInSecond = {300, 600};
5158
5159 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5161 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5162 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005163 // Only the first window should get the down event
5164 firstWindow->consumeMotionDown();
5165 secondWindow->assertNoEvents();
5166
5167 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005168 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5169 ADISPLAY_ID_DEFAULT,
5170 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005171 // The first window gets a move and the second a down
5172 firstWindow->consumeMotionMove();
5173 secondWindow->consumeMotionDown();
5174
5175 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005176 const bool transferred =
5177 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005178 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5179 ASSERT_FALSE(transferred);
5180 firstWindow->assertNoEvents();
5181 secondWindow->assertNoEvents();
5182
5183 // The rest of the dispatch should proceed as normal
5184 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005185 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5186 ADISPLAY_ID_DEFAULT,
5187 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005188 // The first window gets MOVE and the second gets pointer up
5189 firstWindow->consumeMotionMove();
5190 secondWindow->consumeMotionUp();
5191
5192 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005193 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5194 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005195 // The first window gets nothing and the second gets up
5196 firstWindow->consumeMotionUp();
5197 secondWindow->assertNoEvents();
5198}
5199
Arthur Hungabbb9d82021-09-01 14:52:30 +00005200// This case will create two windows and one mirrored window on the default display and mirror
5201// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5202// the windows info of second display before default display.
5203TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5204 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5205 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005206 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005207 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005208 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005209 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005210 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005211
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005212 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005213 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005214
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005215 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005216 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005217
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005218 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005219 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005220
5221 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005222 mDispatcher->onWindowInfosChanged(
5223 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5224 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5225 *secondWindowInPrimary->getInfo()},
5226 {},
5227 0,
5228 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005229
5230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005231 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005232 {50, 50}))
5233 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5234
5235 // Window should receive motion event.
5236 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5237
5238 // Transfer touch focus
5239 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5240 secondWindowInPrimary->getToken()));
5241 // The first window gets cancel.
5242 firstWindowInPrimary->consumeMotionCancel();
5243 secondWindowInPrimary->consumeMotionDown();
5244
5245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005246 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005247 ADISPLAY_ID_DEFAULT, {150, 50}))
5248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5249 firstWindowInPrimary->assertNoEvents();
5250 secondWindowInPrimary->consumeMotionMove();
5251
5252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005253 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005254 {150, 50}))
5255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5256 firstWindowInPrimary->assertNoEvents();
5257 secondWindowInPrimary->consumeMotionUp();
5258}
5259
5260// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5261// 'transferTouch' api.
5262TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5263 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5264 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005265 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005266 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005267 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005268 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005269 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005270
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005271 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005272 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005273
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005274 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005275 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005276
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005277 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005278 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005279
5280 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005281 mDispatcher->onWindowInfosChanged(
5282 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5283 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5284 *secondWindowInPrimary->getInfo()},
5285 {},
5286 0,
5287 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005288
5289 // Touch on second display.
5290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005291 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5292 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5294
5295 // Window should receive motion event.
5296 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5297
5298 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005299 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005300
5301 // The first window gets cancel.
5302 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5303 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5304
5305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005306 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005307 SECOND_DISPLAY_ID, {150, 50}))
5308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5309 firstWindowInPrimary->assertNoEvents();
5310 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5311
5312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005313 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5315 firstWindowInPrimary->assertNoEvents();
5316 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5317}
5318
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005319TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005321 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5322 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005323
Vishnu Nair47074b82020-08-14 11:54:47 -07005324 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005325 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005326 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005327
5328 window->consumeFocusEvent(true);
5329
Prabir Pradhan678438e2023-04-13 19:32:51 +00005330 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005331
5332 // Window should receive key down event.
5333 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005334
5335 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005336 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005337 mFakePolicy->assertUserActivityPoked();
5338}
5339
5340TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5341 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5342 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5343 "Fake Window", ADISPLAY_ID_DEFAULT);
5344
5345 window->setDisableUserActivity(true);
5346 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005347 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005348 setFocusedWindow(window);
5349
5350 window->consumeFocusEvent(true);
5351
5352 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5353
5354 // Window should receive key down event.
5355 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5356
5357 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005358 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005359 mFakePolicy->assertUserActivityNotPoked();
5360}
5361
5362TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5364 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5365 "Fake Window", ADISPLAY_ID_DEFAULT);
5366
5367 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005369 setFocusedWindow(window);
5370
5371 window->consumeFocusEvent(true);
5372
5373 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5374 mDispatcher->waitForIdle();
5375
5376 // System key is not passed down
5377 window->assertNoEvents();
5378
5379 // Should have poked user activity
5380 mFakePolicy->assertUserActivityPoked();
5381}
5382
5383TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5385 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5386 "Fake Window", ADISPLAY_ID_DEFAULT);
5387
5388 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005390 setFocusedWindow(window);
5391
5392 window->consumeFocusEvent(true);
5393
5394 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5395 mDispatcher->waitForIdle();
5396
5397 // System key is not passed down
5398 window->assertNoEvents();
5399
5400 // Should have poked user activity
5401 mFakePolicy->assertUserActivityPoked();
5402}
5403
5404TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5406 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5407 "Fake Window", ADISPLAY_ID_DEFAULT);
5408
5409 window->setDisableUserActivity(true);
5410 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005411 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005412 setFocusedWindow(window);
5413
5414 window->consumeFocusEvent(true);
5415
5416 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5417 mDispatcher->waitForIdle();
5418
5419 // System key is not passed down
5420 window->assertNoEvents();
5421
5422 // Should have poked user activity
5423 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005424}
5425
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005426TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5429 "Fake Window", ADISPLAY_ID_DEFAULT);
5430
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005431 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005432
5433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005434 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005435 ADISPLAY_ID_DEFAULT, {100, 100}))
5436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5437
5438 window->consumeMotionEvent(
5439 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5440
5441 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005442 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005443 mFakePolicy->assertUserActivityPoked();
5444}
5445
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005446TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005448 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5449 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005450
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005451 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005452
Prabir Pradhan678438e2023-04-13 19:32:51 +00005453 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005454 mDispatcher->waitForIdle();
5455
5456 window->assertNoEvents();
5457}
5458
5459// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5460TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005461 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005462 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5463 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005464
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005465 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005466
5467 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005468 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005469 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005470 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5471 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005472
5473 // Window should receive only the motion event
5474 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5475 window->assertNoEvents(); // Key event or focus event will not be received
5476}
5477
arthurhungea3f4fc2020-12-21 23:18:53 +08005478TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5479 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5480
arthurhungea3f4fc2020-12-21 23:18:53 +08005481 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005482 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5483 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005484 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005485
arthurhungea3f4fc2020-12-21 23:18:53 +08005486 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005487 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5488 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005489 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005490
5491 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005492 mDispatcher->onWindowInfosChanged(
5493 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005494
5495 PointF pointInFirst = {300, 200};
5496 PointF pointInSecond = {300, 600};
5497
5498 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5501 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005502 // Only the first window should get the down event
5503 firstWindow->consumeMotionDown();
5504 secondWindow->assertNoEvents();
5505
5506 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005507 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5508 ADISPLAY_ID_DEFAULT,
5509 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005510 // The first window gets a move and the second a down
5511 firstWindow->consumeMotionMove();
5512 secondWindow->consumeMotionDown();
5513
5514 // Send pointer cancel to the second window
5515 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005516 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005517 {pointInFirst, pointInSecond});
5518 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005519 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005520 // The first window gets move and the second gets cancel.
5521 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5522 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5523
5524 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005525 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5526 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005527 // The first window gets up and the second gets nothing.
5528 firstWindow->consumeMotionUp();
5529 secondWindow->assertNoEvents();
5530}
5531
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005532TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5534
5535 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005536 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005537 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005538 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5539 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5540 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5541
Harry Cutts33476232023-01-30 19:57:29 +00005542 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005543 window->assertNoEvents();
5544 mDispatcher->waitForIdle();
5545}
5546
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005547using InputDispatcherMonitorTest = InputDispatcherTest;
5548
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005549/**
5550 * Two entities that receive touch: A window, and a global monitor.
5551 * The touch goes to the window, and then the window disappears.
5552 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5553 * for the monitor, as well.
5554 * 1. foregroundWindow
5555 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5556 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005557TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005558 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5559 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005560 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005561
Prabir Pradhanfb549072023-10-05 19:17:36 +00005562 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005563
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005564 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005566 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005567 {100, 200}))
5568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5569
5570 // Both the foreground window and the global monitor should receive the touch down
5571 window->consumeMotionDown();
5572 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5573
5574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005575 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005576 ADISPLAY_ID_DEFAULT, {110, 200}))
5577 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5578
5579 window->consumeMotionMove();
5580 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5581
5582 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005583 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005584 window->consumeMotionCancel();
5585 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5586
5587 // If more events come in, there will be no more foreground window to send them to. This will
5588 // cause a cancel for the monitor, as well.
5589 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005590 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005591 ADISPLAY_ID_DEFAULT, {120, 200}))
5592 << "Injection should fail because the window was removed";
5593 window->assertNoEvents();
5594 // Global monitor now gets the cancel
5595 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5596}
5597
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005598TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005600 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5601 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005602 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005603
Prabir Pradhanfb549072023-10-05 19:17:36 +00005604 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005605
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005607 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005609 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005610 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005611}
5612
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005613TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005614 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005615
Chris Yea209fde2020-07-22 13:54:51 -07005616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005617 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5618 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005620
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005622 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005624 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005625 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005626
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005627 // Pilfer pointers from the monitor.
5628 // This should not do anything and the window should continue to receive events.
5629 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005630
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005632 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005633 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005635
5636 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5637 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005638}
5639
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005640TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005641 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005642 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5643 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005644 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005645 window->setWindowOffset(20, 40);
5646 window->setWindowTransform(0, 1, -1, 0);
5647
Prabir Pradhanfb549072023-10-05 19:17:36 +00005648 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005649
5650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5653 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5654 MotionEvent* event = monitor.consumeMotion();
5655 // Even though window has transform, gesture monitor must not.
5656 ASSERT_EQ(ui::Transform(), event->getTransform());
5657}
5658
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005659TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005661 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005662
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005663 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005664 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005665 << "Injection should fail if there is a monitor, but no touchable window";
5666 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005667}
5668
chaviw81e2bb92019-12-18 15:03:51 -08005669TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5672 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005675
5676 NotifyMotionArgs motionArgs =
5677 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5678 ADISPLAY_ID_DEFAULT);
5679
Prabir Pradhan678438e2023-04-13 19:32:51 +00005680 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005681 // Window should receive motion down event.
5682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5683
5684 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005685 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005686 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5687 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5688 motionArgs.pointerCoords[0].getX() - 10);
5689
Prabir Pradhan678438e2023-04-13 19:32:51 +00005690 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005691 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005692 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005693}
5694
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005695/**
5696 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5697 * the device default right away. In the test scenario, we check both the default value,
5698 * and the action of enabling / disabling.
5699 */
5700TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005702 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5703 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005704 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005705
5706 // Set focused application.
5707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005708 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005709
5710 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005712 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005713 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005714
5715 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005716 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005718 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005719
5720 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005721 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005722 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005723 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005724 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005726 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005727 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005728
5729 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005730 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005732 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005733
5734 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005735 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005736 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005737 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005738 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005739 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005740 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005741 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005742
5743 window->assertNoEvents();
5744}
5745
Gang Wange9087892020-01-07 12:17:14 -05005746TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5749 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005750
5751 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005752 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005754 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005755 setFocusedWindow(window);
5756
Harry Cutts33476232023-01-30 19:57:29 +00005757 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005758
Prabir Pradhan678438e2023-04-13 19:32:51 +00005759 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5760 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005761
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005762 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005763 ASSERT_NE(event, nullptr);
5764
5765 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5766 ASSERT_NE(verified, nullptr);
5767 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5768
5769 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5770 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5771 ASSERT_EQ(keyArgs.source, verified->source);
5772 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5773
5774 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5775
5776 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005777 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005778 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005779 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5780 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5781 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5782 ASSERT_EQ(0, verifiedKey.repeatCount);
5783}
5784
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005785TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005787 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5788 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005789
5790 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5791
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005792 ui::Transform transform;
5793 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5794
5795 gui::DisplayInfo displayInfo;
5796 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5797 displayInfo.transform = transform;
5798
Patrick Williamsd828f302023-04-28 17:52:08 -05005799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005800
Prabir Pradhan678438e2023-04-13 19:32:51 +00005801 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005802 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5803 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005804 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005805
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005806 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005807 ASSERT_NE(event, nullptr);
5808
5809 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5810 ASSERT_NE(verified, nullptr);
5811 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5812
5813 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5814 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5815 EXPECT_EQ(motionArgs.source, verified->source);
5816 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5817
5818 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5819
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005820 const vec2 rawXY =
5821 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5822 motionArgs.pointerCoords[0].getXYValue());
5823 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5824 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005825 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005826 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005827 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005828 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5829 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5830}
5831
chaviw09c8d2d2020-08-24 15:48:26 -07005832/**
5833 * Ensure that separate calls to sign the same data are generating the same key.
5834 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5835 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5836 * tests.
5837 */
5838TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5839 KeyEvent event = getTestKeyEvent();
5840 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5841
5842 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5843 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5844 ASSERT_EQ(hmac1, hmac2);
5845}
5846
5847/**
5848 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5849 */
5850TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5851 KeyEvent event = getTestKeyEvent();
5852 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5853 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5854
5855 verifiedEvent.deviceId += 1;
5856 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5857
5858 verifiedEvent.source += 1;
5859 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5860
5861 verifiedEvent.eventTimeNanos += 1;
5862 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5863
5864 verifiedEvent.displayId += 1;
5865 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5866
5867 verifiedEvent.action += 1;
5868 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5869
5870 verifiedEvent.downTimeNanos += 1;
5871 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5872
5873 verifiedEvent.flags += 1;
5874 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5875
5876 verifiedEvent.keyCode += 1;
5877 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5878
5879 verifiedEvent.scanCode += 1;
5880 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5881
5882 verifiedEvent.metaState += 1;
5883 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5884
5885 verifiedEvent.repeatCount += 1;
5886 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5887}
5888
Vishnu Nair958da932020-08-21 17:12:37 -07005889TEST_F(InputDispatcherTest, SetFocusedWindow) {
5890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5891 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005892 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005893 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005894 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005895 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5896
5897 // Top window is also focusable but is not granted focus.
5898 windowTop->setFocusable(true);
5899 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005900 mDispatcher->onWindowInfosChanged(
5901 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005902 setFocusedWindow(windowSecond);
5903
5904 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005906 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005907
5908 // Focused window should receive event.
5909 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5910 windowTop->assertNoEvents();
5911}
5912
5913TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5915 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005916 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005917 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5918
5919 window->setFocusable(true);
5920 // Release channel for window is no longer valid.
5921 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005922 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005923 setFocusedWindow(window);
5924
5925 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005926 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005927
5928 // window channel is invalid, so it should not receive any input event.
5929 window->assertNoEvents();
5930}
5931
5932TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5934 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005935 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005936 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005937 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005939 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005940 setFocusedWindow(window);
5941
5942 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005943 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005944
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005945 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005946 window->assertNoEvents();
5947}
5948
5949TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5951 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005952 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005953 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005954 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005955 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5956
5957 windowTop->setFocusable(true);
5958 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005959 mDispatcher->onWindowInfosChanged(
5960 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005961 setFocusedWindow(windowTop);
5962 windowTop->consumeFocusEvent(true);
5963
Chavi Weingarten847e8512023-03-29 00:26:09 +00005964 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005965 mDispatcher->onWindowInfosChanged(
5966 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005967 windowSecond->consumeFocusEvent(true);
5968 windowTop->consumeFocusEvent(false);
5969
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005971 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005972
5973 // Focused window should receive event.
5974 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5975}
5976
Chavi Weingarten847e8512023-03-29 00:26:09 +00005977TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5979 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005980 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005981 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005982 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005983 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5984
5985 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005986 windowSecond->setFocusable(false);
5987 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005988 mDispatcher->onWindowInfosChanged(
5989 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005990 setFocusedWindow(windowTop);
5991 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005992
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005994 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005995
5996 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005997 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005998 windowSecond->assertNoEvents();
5999}
6000
6001TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6003 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006004 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006005 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006006 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6007 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006008 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6009
6010 window->setFocusable(true);
6011 previousFocusedWindow->setFocusable(true);
6012 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006013 mDispatcher->onWindowInfosChanged(
6014 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006015 setFocusedWindow(previousFocusedWindow);
6016 previousFocusedWindow->consumeFocusEvent(true);
6017
6018 // Requesting focus on invisible window takes focus from currently focused window.
6019 setFocusedWindow(window);
6020 previousFocusedWindow->consumeFocusEvent(false);
6021
6022 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006024 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6025 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006026
6027 // Window does not get focus event or key down.
6028 window->assertNoEvents();
6029
6030 // Window becomes visible.
6031 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006032 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006033
6034 // Window receives focus event.
6035 window->consumeFocusEvent(true);
6036 // Focused window receives key down.
6037 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6038}
6039
Vishnu Nair599f1412021-06-21 10:39:58 -07006040TEST_F(InputDispatcherTest, DisplayRemoved) {
6041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6042 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006043 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6045
6046 // window is granted focus.
6047 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006048 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006049 setFocusedWindow(window);
6050 window->consumeFocusEvent(true);
6051
6052 // When a display is removed window loses focus.
6053 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6054 window->consumeFocusEvent(false);
6055}
6056
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006057/**
6058 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6059 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6060 * of the 'slipperyEnterWindow'.
6061 *
6062 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6063 * a way so that the touched location is no longer covered by the top window.
6064 *
6065 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6066 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6067 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6068 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6069 * with ACTION_DOWN).
6070 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6071 * window moved itself away from the touched location and had Flag::SLIPPERY.
6072 *
6073 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6074 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6075 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6076 *
6077 * In this test, we ensure that the event received by the bottom window has
6078 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6079 */
6080TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006081 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006082 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006083
6084 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6085 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6086
6087 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006088 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006089 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006090 // Make sure this one overlaps the bottom window
6091 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6092 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6093 // one. Windows with the same owner are not considered to be occluding each other.
6094 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6095
6096 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006097 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006098 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6099
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006100 mDispatcher->onWindowInfosChanged(
6101 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006102
6103 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006104 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6105 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6106 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006107 slipperyExitWindow->consumeMotionDown();
6108 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006109 mDispatcher->onWindowInfosChanged(
6110 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006111
Prabir Pradhan678438e2023-04-13 19:32:51 +00006112 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6114 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006115
6116 slipperyExitWindow->consumeMotionCancel();
6117
6118 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6119 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6120}
6121
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006122/**
6123 * Two windows, one on the left and another on the right. The left window is slippery. The right
6124 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6125 * touch moves from the left window into the right window, the gesture should continue to go to the
6126 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6127 * reproduces a crash.
6128 */
6129TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6131
6132 sp<FakeWindowHandle> leftSlipperyWindow =
6133 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6134 leftSlipperyWindow->setSlippery(true);
6135 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6136
6137 sp<FakeWindowHandle> rightDropTouchesWindow =
6138 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6139 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6140 rightDropTouchesWindow->setDropInput(true);
6141
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged(
6143 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006144
6145 // Start touch in the left window
6146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6147 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6148 .build());
6149 leftSlipperyWindow->consumeMotionDown();
6150
6151 // And move it into the right window
6152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6153 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6154 .build());
6155
6156 // Since the right window isn't eligible to receive input, touch does not slip.
6157 // The left window continues to receive the gesture.
6158 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6159 rightDropTouchesWindow->assertNoEvents();
6160}
6161
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006162/**
6163 * A single window is on screen first. Touch is injected into that window. Next, a second window
6164 * appears. Since the first window is slippery, touch will move from the first window to the second.
6165 */
6166TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6168 sp<FakeWindowHandle> originalWindow =
6169 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6170 originalWindow->setFrame(Rect(0, 0, 200, 200));
6171 originalWindow->setSlippery(true);
6172
6173 sp<FakeWindowHandle> appearingWindow =
6174 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6175 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6176
6177 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6178
6179 // Touch down on the original window
6180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6181 injectMotionEvent(*mDispatcher,
6182 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6183 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6184 .build()));
6185 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6186
6187 // Now, a new window appears. This could be, for example, a notification shade that appears
6188 // after user starts to drag down on the launcher window.
6189 mDispatcher->onWindowInfosChanged(
6190 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6192 injectMotionEvent(*mDispatcher,
6193 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6194 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6195 .build()));
6196 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6197 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6199 injectMotionEvent(*mDispatcher,
6200 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6201 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6202 .build()));
6203 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6204
6205 originalWindow->assertNoEvents();
6206 appearingWindow->assertNoEvents();
6207}
6208
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006209TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006210 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6212
6213 sp<FakeWindowHandle> leftWindow =
6214 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6215 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006216 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006217
6218 sp<FakeWindowHandle> rightSpy =
6219 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6220 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006221 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006222 rightSpy->setSpy(true);
6223 rightSpy->setTrustedOverlay(true);
6224
6225 sp<FakeWindowHandle> rightWindow =
6226 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6227 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006228 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006229
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006230 mDispatcher->onWindowInfosChanged(
6231 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006232
6233 // Touch in the left window
6234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6235 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6236 .build());
6237 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6238 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006239 ASSERT_NO_FATAL_FAILURE(
6240 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006241
6242 // Touch another finger over the right windows
6243 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6244 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6245 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6246 .build());
6247 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6248 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6249 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6250 mDispatcher->waitForIdle();
6251 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006252 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6253 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006254
6255 // Release finger over left window. The UP actions are not treated as device interaction.
6256 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6257 // is part of the UP action, we do not treat this as device interaction.
6258 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6259 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6260 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6261 .build());
6262 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6263 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6264 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6265 mDispatcher->waitForIdle();
6266 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6267
6268 // Move remaining finger
6269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6270 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6271 .build());
6272 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6273 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6274 mDispatcher->waitForIdle();
6275 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006276 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006277
6278 // Release all fingers
6279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6280 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6281 .build());
6282 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6283 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6284 mDispatcher->waitForIdle();
6285 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6286}
6287
6288TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6290
6291 sp<FakeWindowHandle> window =
6292 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6293 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006294 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006295
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006296 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006297 setFocusedWindow(window);
6298 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6299
6300 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6301 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6302 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006303 ASSERT_NO_FATAL_FAILURE(
6304 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006305
6306 // The UP actions are not treated as device interaction.
6307 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6308 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6309 mDispatcher->waitForIdle();
6310 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6311}
6312
Garfield Tan1c7bc862020-01-28 13:24:04 -08006313class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6314protected:
6315 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6316 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6317
Chris Yea209fde2020-07-22 13:54:51 -07006318 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006319 sp<FakeWindowHandle> mWindow;
6320
6321 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006322 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006323 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006324 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006325 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006326 ASSERT_EQ(OK, mDispatcher->start());
6327
6328 setUpWindow();
6329 }
6330
6331 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006332 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006333 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006334
Vishnu Nair47074b82020-08-14 11:54:47 -07006335 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006336 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006337 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006338 mWindow->consumeFocusEvent(true);
6339 }
6340
Chris Ye2ad95392020-09-01 13:44:44 -07006341 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006342 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006343 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006344 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006345 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006346
6347 // Window should receive key down event.
6348 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6349 }
6350
6351 void expectKeyRepeatOnce(int32_t repeatCount) {
6352 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006353 mWindow->consumeKeyEvent(
6354 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006355 }
6356
Chris Ye2ad95392020-09-01 13:44:44 -07006357 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006358 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006359 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006360 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006361 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006362
6363 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006364 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006365 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006366 }
6367};
6368
6369TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006370 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006371 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6372 expectKeyRepeatOnce(repeatCount);
6373 }
6374}
6375
6376TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006377 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006378 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6379 expectKeyRepeatOnce(repeatCount);
6380 }
Harry Cutts33476232023-01-30 19:57:29 +00006381 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006382 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006383 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6384 expectKeyRepeatOnce(repeatCount);
6385 }
6386}
6387
6388TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006389 sendAndConsumeKeyDown(/*deviceId=*/1);
6390 expectKeyRepeatOnce(/*repeatCount=*/1);
6391 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006392 mWindow->assertNoEvents();
6393}
6394
6395TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006396 sendAndConsumeKeyDown(/*deviceId=*/1);
6397 expectKeyRepeatOnce(/*repeatCount=*/1);
6398 sendAndConsumeKeyDown(/*deviceId=*/2);
6399 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006400 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006401 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006402 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006403 expectKeyRepeatOnce(/*repeatCount=*/2);
6404 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006405 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006406 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006407 mWindow->assertNoEvents();
6408}
6409
6410TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006411 sendAndConsumeKeyDown(/*deviceId=*/1);
6412 expectKeyRepeatOnce(/*repeatCount=*/1);
6413 sendAndConsumeKeyDown(/*deviceId=*/2);
6414 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006415 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006416 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006417 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006418 mWindow->assertNoEvents();
6419}
6420
liushenxiang42232912021-05-21 20:24:09 +08006421TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6422 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006423 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006424 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006425 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6426 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6427 mWindow->assertNoEvents();
6428}
6429
Garfield Tan1c7bc862020-01-28 13:24:04 -08006430TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006431 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006432 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006433 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006434 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006435 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6436 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6437 IdGenerator::getSource(repeatEvent->getId()));
6438 }
6439}
6440
6441TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006442 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006443 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006444
6445 std::unordered_set<int32_t> idSet;
6446 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006447 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006448 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6449 int32_t id = repeatEvent->getId();
6450 EXPECT_EQ(idSet.end(), idSet.find(id));
6451 idSet.insert(id);
6452 }
6453}
6454
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006455/* Test InputDispatcher for MultiDisplay */
6456class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6457public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006458 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006459 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006460
Chris Yea209fde2020-07-22 13:54:51 -07006461 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006462 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006463 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006464
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006465 // Set focus window for primary display, but focused display would be second one.
6466 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006467 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006468 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6469
Vishnu Nair958da932020-08-21 17:12:37 -07006470 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006471 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006472
Chris Yea209fde2020-07-22 13:54:51 -07006473 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006474 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006475 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006476 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006477 // Set focus display to second one.
6478 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6479 // Set focus window for second display.
6480 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006481 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006482 mDispatcher->onWindowInfosChanged(
6483 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006484 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006485 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006486 }
6487
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006488 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006489 InputDispatcherTest::TearDown();
6490
Chris Yea209fde2020-07-22 13:54:51 -07006491 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006492 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006493 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006494 windowInSecondary.clear();
6495 }
6496
6497protected:
Chris Yea209fde2020-07-22 13:54:51 -07006498 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006499 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006500 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006501 sp<FakeWindowHandle> windowInSecondary;
6502};
6503
6504TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6505 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006507 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006508 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006509 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006510 windowInSecondary->assertNoEvents();
6511
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006512 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006516 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006517 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006518}
6519
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006520TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006521 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006523 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006524 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006525 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006526 windowInSecondary->assertNoEvents();
6527
6528 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006530 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006531 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006532 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006533
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006534 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006535 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006536
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006537 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006538 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006539 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006540
6541 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006542 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006543 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006544 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006545 windowInSecondary->assertNoEvents();
6546}
6547
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006548// Test per-display input monitors for motion event.
6549TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006550 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006551 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006552 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006553 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006554
6555 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006557 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006559 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006560 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006561 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006562 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006563
6564 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006566 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006568 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006569 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006570 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006571 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006572
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006573 // Lift up the touch from the second display
6574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006575 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6577 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6578 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6579
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006580 // Test inject a non-pointer motion event.
6581 // If specific a display, it will dispatch to the focused window of particular display,
6582 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006584 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006586 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006587 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006588 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006589 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006590}
6591
6592// Test per-display input monitors for key event.
6593TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006594 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006595 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006596 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006597 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006598 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006599
6600 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006602 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006603 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006604 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006605 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006606 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006607}
6608
Vishnu Nair958da932020-08-21 17:12:37 -07006609TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6610 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006611 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006612 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006613 mDispatcher->onWindowInfosChanged(
6614 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6615 *windowInSecondary->getInfo()},
6616 {},
6617 0,
6618 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006619 setFocusedWindow(secondWindowInPrimary);
6620 windowInPrimary->consumeFocusEvent(false);
6621 secondWindowInPrimary->consumeFocusEvent(true);
6622
6623 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6625 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006626 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006627 windowInPrimary->assertNoEvents();
6628 windowInSecondary->assertNoEvents();
6629 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6630}
6631
Arthur Hungdfd528e2021-12-08 13:23:04 +00006632TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6633 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006634 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006635 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006636 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006637
6638 // Test touch down on primary display.
6639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006640 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6642 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6643 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6644
6645 // Test touch down on second display.
6646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006647 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6649 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6650 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6651
6652 // Trigger cancel touch.
6653 mDispatcher->cancelCurrentTouch();
6654 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6655 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6656 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6657 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6658
6659 // Test inject a move motion event, no window/monitor should receive the event.
6660 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006661 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006662 ADISPLAY_ID_DEFAULT, {110, 200}))
6663 << "Inject motion event should return InputEventInjectionResult::FAILED";
6664 windowInPrimary->assertNoEvents();
6665 monitorInPrimary.assertNoEvents();
6666
6667 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006668 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006669 SECOND_DISPLAY_ID, {110, 200}))
6670 << "Inject motion event should return InputEventInjectionResult::FAILED";
6671 windowInSecondary->assertNoEvents();
6672 monitorInSecondary.assertNoEvents();
6673}
6674
Jackal Guof9696682018-10-05 12:23:23 +08006675class InputFilterTest : public InputDispatcherTest {
6676protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006677 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6678 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006679 NotifyMotionArgs motionArgs;
6680
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006681 motionArgs =
6682 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006683 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006684 motionArgs =
6685 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006686 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006687 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006688 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006689 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006690 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006691 } else {
6692 mFakePolicy->assertFilterInputEventWasNotCalled();
6693 }
6694 }
6695
6696 void testNotifyKey(bool expectToBeFiltered) {
6697 NotifyKeyArgs keyArgs;
6698
6699 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006700 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006701 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006702 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006703 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006704
6705 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006706 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006707 } else {
6708 mFakePolicy->assertFilterInputEventWasNotCalled();
6709 }
6710 }
6711};
6712
6713// Test InputFilter for MotionEvent
6714TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6715 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006716 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6717 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006718
6719 // Enable InputFilter
6720 mDispatcher->setInputFilterEnabled(true);
6721 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006722 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6723 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006724
6725 // Disable InputFilter
6726 mDispatcher->setInputFilterEnabled(false);
6727 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006728 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6729 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006730}
6731
6732// Test InputFilter for KeyEvent
6733TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6734 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006735 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006736
6737 // Enable InputFilter
6738 mDispatcher->setInputFilterEnabled(true);
6739 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006740 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006741
6742 // Disable InputFilter
6743 mDispatcher->setInputFilterEnabled(false);
6744 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006745 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006746}
6747
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006748// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6749// logical display coordinate space.
6750TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6751 ui::Transform firstDisplayTransform;
6752 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6753 ui::Transform secondDisplayTransform;
6754 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6755
6756 std::vector<gui::DisplayInfo> displayInfos(2);
6757 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6758 displayInfos[0].transform = firstDisplayTransform;
6759 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6760 displayInfos[1].transform = secondDisplayTransform;
6761
Patrick Williamsd828f302023-04-28 17:52:08 -05006762 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006763
6764 // Enable InputFilter
6765 mDispatcher->setInputFilterEnabled(true);
6766
6767 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006768 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6769 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006770}
6771
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006772class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6773protected:
6774 virtual void SetUp() override {
6775 InputDispatcherTest::SetUp();
6776
6777 /**
6778 * We don't need to enable input filter to test the injected event policy, but we enabled it
6779 * here to make the tests more realistic, since this policy only matters when inputfilter is
6780 * on.
6781 */
6782 mDispatcher->setInputFilterEnabled(true);
6783
6784 std::shared_ptr<InputApplicationHandle> application =
6785 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006786 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6787 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006788
6789 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6790 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006791 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006792 setFocusedWindow(mWindow);
6793 mWindow->consumeFocusEvent(true);
6794 }
6795
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006796 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6797 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006798 KeyEvent event;
6799
6800 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6801 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6802 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006803 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006804 const int32_t additionalPolicyFlags =
6805 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006807 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006808 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006809 policyFlags | additionalPolicyFlags));
6810
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006811 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006812 }
6813
6814 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6815 int32_t flags) {
6816 MotionEvent event;
6817 PointerProperties pointerProperties[1];
6818 PointerCoords pointerCoords[1];
6819 pointerProperties[0].clear();
6820 pointerProperties[0].id = 0;
6821 pointerCoords[0].clear();
6822 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6823 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6824
6825 ui::Transform identityTransform;
6826 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6827 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6828 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6829 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6830 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006831 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006832 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006833 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006834
6835 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006838 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006839 policyFlags | additionalPolicyFlags));
6840
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006841 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006842 }
6843
6844private:
6845 sp<FakeWindowHandle> mWindow;
6846};
6847
6848TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006849 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6850 // filter. Without it, the event will no different from a regularly injected event, and the
6851 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006852 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6853 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006854}
6855
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006856TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006857 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006858 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006859 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6860}
6861
6862TEST_F(InputFilterInjectionPolicyTest,
6863 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6864 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006865 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006866 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006867}
6868
6869TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006870 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6871 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006872}
6873
chaviwfd6d3512019-03-25 13:23:49 -07006874class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006875 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006876 InputDispatcherTest::SetUp();
6877
Chris Yea209fde2020-07-22 13:54:51 -07006878 std::shared_ptr<FakeApplicationHandle> application =
6879 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006880 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006881 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006882 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006883
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006884 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006885 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006886 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006887
6888 // Set focused application.
6889 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006890 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006891
6892 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006893 mDispatcher->onWindowInfosChanged(
6894 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006895 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006896 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006897 }
6898
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006899 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006900 InputDispatcherTest::TearDown();
6901
6902 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006903 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006904 }
6905
6906protected:
6907 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006908 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006909 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006910};
6911
6912// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6913// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6914// the onPointerDownOutsideFocus callback.
6915TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006917 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006918 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006920 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006921
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006922 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006923 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6924}
6925
6926// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6927// DOWN on the window that doesn't have focus. Ensure no window received the
6928// onPointerDownOutsideFocus callback.
6929TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006931 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6932 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006933 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006934 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006935
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006936 ASSERT_TRUE(mDispatcher->waitForIdle());
6937 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006938}
6939
6940// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6941// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6942TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006944 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006945 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006946 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006947
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006948 ASSERT_TRUE(mDispatcher->waitForIdle());
6949 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006950}
6951
6952// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6953// DOWN on the window that already has focus. Ensure no window received the
6954// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006955TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006957 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006958 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006960 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006961
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006962 ASSERT_TRUE(mDispatcher->waitForIdle());
6963 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006964}
6965
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006966// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6967// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6968TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6969 const MotionEvent event =
6970 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6971 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006972 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006973 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6974 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6977 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6978
6979 ASSERT_TRUE(mDispatcher->waitForIdle());
6980 mFakePolicy->assertOnPointerDownWasNotCalled();
6981 // Ensure that the unfocused window did not receive any FOCUS events.
6982 mUnfocusedWindow->assertNoEvents();
6983}
6984
chaviwaf87b3e2019-10-01 16:59:28 -07006985// These tests ensures we can send touch events to a single client when there are multiple input
6986// windows that point to the same client token.
6987class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6988 virtual void SetUp() override {
6989 InputDispatcherTest::SetUp();
6990
Chris Yea209fde2020-07-22 13:54:51 -07006991 std::shared_ptr<FakeApplicationHandle> application =
6992 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006993 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6994 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006995 mWindow1->setFrame(Rect(0, 0, 100, 100));
6996
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006997 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6998 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006999 mWindow2->setFrame(Rect(100, 100, 200, 200));
7000
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007001 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007002 }
7003
7004protected:
7005 sp<FakeWindowHandle> mWindow1;
7006 sp<FakeWindowHandle> mWindow2;
7007
7008 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007009 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007010 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7011 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007012 }
7013
7014 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7015 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007016 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007017 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007018
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007019 ASSERT_NE(nullptr, motionEvent)
7020 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007021
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007022 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007023 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007024
7025 for (size_t i = 0; i < points.size(); i++) {
7026 float expectedX = points[i].x;
7027 float expectedY = points[i].y;
7028
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007029 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007030 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007031 << ", got " << motionEvent->getX(i);
7032 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007033 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007034 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007035 }
7036 }
chaviw9eaa22c2020-07-01 16:21:27 -07007037
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007038 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007039 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007040 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7041 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007042
7043 // Always consume from window1 since it's the window that has the InputReceiver
7044 consumeMotionEvent(mWindow1, action, expectedPoints);
7045 }
chaviwaf87b3e2019-10-01 16:59:28 -07007046};
7047
7048TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7049 // Touch Window 1
7050 PointF touchedPoint = {10, 10};
7051 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007052 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007053
7054 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007055 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007056
7057 // Touch Window 2
7058 touchedPoint = {150, 150};
7059 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007060 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007061}
7062
chaviw9eaa22c2020-07-01 16:21:27 -07007063TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7064 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007065 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007066 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007067
7068 // Touch Window 1
7069 PointF touchedPoint = {10, 10};
7070 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007071 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007072 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007073 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007074
7075 // Touch Window 2
7076 touchedPoint = {150, 150};
7077 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007078 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7079 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007080
chaviw9eaa22c2020-07-01 16:21:27 -07007081 // Update the transform so rotation is set
7082 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007083 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007084 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7085 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007086}
7087
chaviw9eaa22c2020-07-01 16:21:27 -07007088TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007089 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007090 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007091
7092 // Touch Window 1
7093 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7094 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007095 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007096
7097 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007098 touchedPoints.push_back(PointF{150, 150});
7099 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007100 touchAndAssertPositions(POINTER_1_DOWN, 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();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007105
chaviw9eaa22c2020-07-01 16:21:27 -07007106 // Update the transform so rotation is set for 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);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007111}
7112
chaviw9eaa22c2020-07-01 16:21:27 -07007113TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007114 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007115 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007116
7117 // Touch Window 1
7118 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7119 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007120 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007121
7122 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007123 touchedPoints.push_back(PointF{150, 150});
7124 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007125
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007126 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007127
7128 // Move both windows
7129 touchedPoints = {{20, 20}, {175, 175}};
7130 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7131 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7132
chaviw9eaa22c2020-07-01 16:21:27 -07007133 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007134
chaviw9eaa22c2020-07-01 16:21:27 -07007135 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007136 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007137 expectedPoints.pop_back();
7138
7139 // Touch Window 2
7140 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007141 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007142 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007143 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007144
7145 // Move both windows
7146 touchedPoints = {{20, 20}, {175, 175}};
7147 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7148 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7149
7150 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007151}
7152
7153TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7154 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007155 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007156
7157 // Touch Window 1
7158 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7159 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007160 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007161
7162 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007163 touchedPoints.push_back(PointF{150, 150});
7164 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007165
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007166 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007167
7168 // Move both windows
7169 touchedPoints = {{20, 20}, {175, 175}};
7170 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7171 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7172
chaviw9eaa22c2020-07-01 16:21:27 -07007173 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007174}
7175
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007176/**
7177 * When one of the windows is slippery, the touch should not slip into the other window with the
7178 * same input channel.
7179 */
7180TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7181 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007182 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007183
7184 // Touch down in window 1
7185 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7186 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7187 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7188
7189 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7190 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7191 // getting generated.
7192 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7193 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7194
7195 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7196}
7197
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007198/**
7199 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7200 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7201 * that the pointer is hovering over may have a different transform.
7202 */
7203TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007204 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007205
7206 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7208 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7209 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007210 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7211 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007212 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7214 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7215 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007216 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7217 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7218 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7219}
7220
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007221class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7222 virtual void SetUp() override {
7223 InputDispatcherTest::SetUp();
7224
Chris Yea209fde2020-07-22 13:54:51 -07007225 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007226 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007227 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7228 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007229 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007230 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007231 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007232
7233 // Set focused application.
7234 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7235
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007236 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007237 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007238 mWindow->consumeFocusEvent(true);
7239 }
7240
7241 virtual void TearDown() override {
7242 InputDispatcherTest::TearDown();
7243 mWindow.clear();
7244 }
7245
7246protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007247 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007248 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007249 sp<FakeWindowHandle> mWindow;
7250 static constexpr PointF WINDOW_LOCATION = {20, 20};
7251
7252 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007255 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007257 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007258 WINDOW_LOCATION));
7259 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007260
7261 sp<FakeWindowHandle> addSpyWindow() {
7262 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007263 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007264 spy->setTrustedOverlay(true);
7265 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007266 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007267 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007268 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007269 return spy;
7270 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007271};
7272
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007273// Send a tap and respond, which should not cause an ANR.
7274TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7275 tapOnWindow();
7276 mWindow->consumeMotionDown();
7277 mWindow->consumeMotionUp();
7278 ASSERT_TRUE(mDispatcher->waitForIdle());
7279 mFakePolicy->assertNotifyAnrWasNotCalled();
7280}
7281
7282// Send a regular key and respond, which should not cause an ANR.
7283TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007285 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7286 ASSERT_TRUE(mDispatcher->waitForIdle());
7287 mFakePolicy->assertNotifyAnrWasNotCalled();
7288}
7289
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007290TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7291 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007292 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007293 mWindow->consumeFocusEvent(false);
7294
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007295 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007296 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7297 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007298 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007300 // Key will not go to window because we have no focused window.
7301 // The 'no focused window' ANR timer should start instead.
7302
7303 // Now, the focused application goes away.
7304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7305 // The key should get dropped and there should be no ANR.
7306
7307 ASSERT_TRUE(mDispatcher->waitForIdle());
7308 mFakePolicy->assertNotifyAnrWasNotCalled();
7309}
7310
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007311// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007312// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7313// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007314TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007316 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007317 WINDOW_LOCATION));
7318
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007319 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7320 ASSERT_TRUE(sequenceNum);
7321 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007322 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007323
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007324 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007325 mWindow->consumeMotionEvent(
7326 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007327 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007328 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007329}
7330
7331// Send a key to the app and have the app not respond right away.
7332TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7333 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007335 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7336 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007337 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007338 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007339 ASSERT_TRUE(mDispatcher->waitForIdle());
7340}
7341
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007342// We have a focused application, but no focused window
7343TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007344 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007345 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007346 mWindow->consumeFocusEvent(false);
7347
7348 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007350 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007351 WINDOW_LOCATION));
7352 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7353 mDispatcher->waitForIdle();
7354 mFakePolicy->assertNotifyAnrWasNotCalled();
7355
7356 // Once a focused event arrives, we get an ANR for this application
7357 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7358 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007359 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007360 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007361 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007362 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007363 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007364 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007365 ASSERT_TRUE(mDispatcher->waitForIdle());
7366}
7367
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007368/**
7369 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7370 * there will not be an ANR.
7371 */
7372TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7373 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007374 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007375 mWindow->consumeFocusEvent(false);
7376
7377 KeyEvent event;
7378 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7379 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7380
7381 // Define a valid key down event that is stale (too old).
7382 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007383 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007384 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007385
7386 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7387
7388 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007389 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007390 InputEventInjectionSync::WAIT_FOR_RESULT,
7391 INJECT_EVENT_TIMEOUT, policyFlags);
7392 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7393 << "Injection should fail because the event is stale";
7394
7395 ASSERT_TRUE(mDispatcher->waitForIdle());
7396 mFakePolicy->assertNotifyAnrWasNotCalled();
7397 mWindow->assertNoEvents();
7398}
7399
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007400// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007401// Make sure that we don't notify policy twice about the same ANR.
7402TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007403 const std::chrono::duration appTimeout = 400ms;
7404 mApplication->setDispatchingTimeout(appTimeout);
7405 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7406
Vishnu Nair47074b82020-08-14 11:54:47 -07007407 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007408 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410
7411 // Once a focused event arrives, we get an ANR for this application
7412 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7413 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007414 const std::chrono::duration eventInjectionTimeout = 100ms;
7415 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007416 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007417 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007418 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7419 /*allowKeyRepeat=*/false);
7420 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7421 << "result=" << ftl::enum_string(result);
7422 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7423 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7424 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7425 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007426
Vishnu Naire4df8752022-09-08 09:17:55 -07007427 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007428 // ANR should not be raised again. It is up to policy to do that if it desires.
7429 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007430
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007431 // If we now get a focused window, the ANR should stop, but the policy handles that via
7432 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007433 ASSERT_TRUE(mDispatcher->waitForIdle());
7434}
7435
7436// We have a focused application, but no focused window
7437TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007438 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007439 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007440 mWindow->consumeFocusEvent(false);
7441
7442 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007443 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007444
Vishnu Naire4df8752022-09-08 09:17:55 -07007445 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7446 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007447
7448 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007449 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007450 ASSERT_TRUE(mDispatcher->waitForIdle());
7451 mWindow->assertNoEvents();
7452}
7453
7454/**
7455 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7456 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7457 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7458 * the ANR mechanism should still work.
7459 *
7460 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7461 * DOWN event, while not responding on the second one.
7462 */
7463TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7464 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007465 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007466 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7467 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7468 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007470
7471 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007472 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7474 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7475 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007476 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007477
7478 // We have now sent down and up. Let's consume first event and then ANR on the second.
7479 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7480 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007481 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007482}
7483
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007484// A spy window can receive an ANR
7485TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7486 sp<FakeWindowHandle> spy = addSpyWindow();
7487
7488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007489 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007490 WINDOW_LOCATION));
7491 mWindow->consumeMotionDown();
7492
7493 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7494 ASSERT_TRUE(sequenceNum);
7495 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007496 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007497
7498 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007499 spy->consumeMotionEvent(
7500 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007501 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007502 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007503}
7504
7505// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007506// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007507TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7508 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007509
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007512 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007514
7515 // Stuck on the ACTION_UP
7516 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007517 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007518
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007519 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007520 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007521 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7522 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007523
7524 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7525 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007526 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007527 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007528 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007529}
7530
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007531// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007532// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007533TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7534 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007535
7536 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007537 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7538 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007539
7540 mWindow->consumeMotionDown();
7541 // Stuck on the ACTION_UP
7542 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007543 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007544
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007545 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007546 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007547 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7548 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007549
7550 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7551 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007552 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007553 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007554 spy->assertNoEvents();
7555}
7556
7557TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007558 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007559
Prabir Pradhanfb549072023-10-05 19:17:36 +00007560 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007561
7562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007563 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007564 WINDOW_LOCATION));
7565
7566 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7567 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7568 ASSERT_TRUE(consumeSeq);
7569
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007570 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7571 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007572
7573 monitor.finishEvent(*consumeSeq);
7574 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7575
7576 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007577 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007578}
7579
7580// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7581// process events, you don't get an anr. When the window later becomes unresponsive again, you
7582// get an ANR again.
7583// 1. tap -> block on ACTION_UP -> receive ANR
7584// 2. consume all pending events (= queue becomes healthy again)
7585// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7586TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7587 tapOnWindow();
7588
7589 mWindow->consumeMotionDown();
7590 // Block on ACTION_UP
7591 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007592 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007593 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7594 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007595 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007596 mWindow->assertNoEvents();
7597
7598 tapOnWindow();
7599 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007600 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007601 mWindow->consumeMotionUp();
7602
7603 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007604 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007605 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007606 mWindow->assertNoEvents();
7607}
7608
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007609// If a connection remains unresponsive for a while, make sure policy is only notified once about
7610// it.
7611TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007613 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007614 WINDOW_LOCATION));
7615
7616 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007617 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007618 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007619 // 'notifyConnectionUnresponsive' should only be called once per connection
7620 mFakePolicy->assertNotifyAnrWasNotCalled();
7621 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007622 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007623 mWindow->consumeMotionEvent(
7624 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007625 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007626 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007627 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007628 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007629}
7630
7631/**
7632 * 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 -07007633 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007634 *
7635 * Warning!!!
7636 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7637 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007638 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007639 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7640 *
7641 * If that value changes, this test should also change.
7642 */
7643TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7644 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007645 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007646
7647 tapOnWindow();
7648 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7649 ASSERT_TRUE(downSequenceNum);
7650 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7651 ASSERT_TRUE(upSequenceNum);
7652 // Don't finish the events yet, and send a key
7653 // Injection will "succeed" because we will eventually give up and send the key to the focused
7654 // window even if motions are still being processed. But because the injection timeout is short,
7655 // we will receive INJECTION_TIMED_OUT as the result.
7656
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007657 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007658 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7659 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007660 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007661 // Key will not be sent to the window, yet, because the window is still processing events
7662 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007663 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7664 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7665 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7666 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007667
7668 std::this_thread::sleep_for(500ms);
7669 // if we wait long enough though, dispatcher will give up, and still send the key
7670 // to the focused window, even though we have not yet finished the motion event
7671 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7672 mWindow->finishEvent(*downSequenceNum);
7673 mWindow->finishEvent(*upSequenceNum);
7674}
7675
7676/**
7677 * If a window is processing a motion event, and then a key event comes in, the key event should
7678 * not go to the focused window until the motion is processed.
7679 * If then a new motion comes in, then the pending key event should be going to the currently
7680 * focused window right away.
7681 */
7682TEST_F(InputDispatcherSingleWindowAnr,
7683 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7684 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007685 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007686
7687 tapOnWindow();
7688 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7689 ASSERT_TRUE(downSequenceNum);
7690 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7691 ASSERT_TRUE(upSequenceNum);
7692 // Don't finish the events yet, and send a key
7693 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007695 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7696 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007697 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007698 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7699 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7700 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7701 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007702
7703 // Now tap down again. It should cause the pending key to go to the focused window right away.
7704 tapOnWindow();
7705 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7706 // the other events yet. We can finish events in any order.
7707 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7708 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7709 mWindow->consumeMotionDown();
7710 mWindow->consumeMotionUp();
7711 mWindow->assertNoEvents();
7712}
7713
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007714/**
7715 * Send an event to the app and have the app not respond right away.
7716 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7717 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7718 * At some point, the window becomes responsive again.
7719 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7720 */
7721TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7723 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7724 .build());
7725
7726 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7727 ASSERT_TRUE(sequenceNum);
7728 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7729 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7730
7731 mWindow->finishEvent(*sequenceNum);
7732 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7733 ASSERT_TRUE(mDispatcher->waitForIdle());
7734 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7735
7736 // Now that the window is responsive, let's continue the gesture.
7737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7738 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7739 .build());
7740
7741 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7742 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7743 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7744 .build());
7745
7746 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7747 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7748 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7749 .build());
7750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7751 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7752 .build());
7753 // We already canceled this pointer, so the window shouldn't get any new events.
7754 mWindow->assertNoEvents();
7755
7756 // Start another one.
7757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7758 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7759 .build());
7760 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7761}
7762
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007763class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7764 virtual void SetUp() override {
7765 InputDispatcherTest::SetUp();
7766
Chris Yea209fde2020-07-22 13:54:51 -07007767 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007768 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007769 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7770 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007771 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007772 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007773 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007774
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007775 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7776 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007777 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007778 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779
7780 // Set focused application.
7781 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007782 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007783
7784 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007785 mDispatcher->onWindowInfosChanged(
7786 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007787 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007788 mFocusedWindow->consumeFocusEvent(true);
7789 }
7790
7791 virtual void TearDown() override {
7792 InputDispatcherTest::TearDown();
7793
7794 mUnfocusedWindow.clear();
7795 mFocusedWindow.clear();
7796 }
7797
7798protected:
Chris Yea209fde2020-07-22 13:54:51 -07007799 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007800 sp<FakeWindowHandle> mUnfocusedWindow;
7801 sp<FakeWindowHandle> mFocusedWindow;
7802 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7803 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7804 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7805
7806 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7807
7808 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7809
7810private:
7811 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007813 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007814 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007816 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007817 location));
7818 }
7819};
7820
7821// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7822// should be ANR'd first.
7823TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007826 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007828 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007829 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007830 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007831 // We consumed all events, so no ANR
7832 ASSERT_TRUE(mDispatcher->waitForIdle());
7833 mFakePolicy->assertNotifyAnrWasNotCalled();
7834
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007837 FOCUSED_WINDOW_LOCATION));
7838 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7839 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007840
7841 const std::chrono::duration timeout =
7842 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007843 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007844 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7845 // sequence to make it consistent
7846 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007847 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007848 mFocusedWindow->consumeMotionDown();
7849 // This cancel is generated because the connection was unresponsive
7850 mFocusedWindow->consumeMotionCancel();
7851 mFocusedWindow->assertNoEvents();
7852 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007853 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007854 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7855 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007856 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007857}
7858
7859// If we have 2 windows with identical timeouts that are both unresponsive,
7860// it doesn't matter which order they should have ANR.
7861// But we should receive ANR for both.
7862TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7863 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007864 mUnfocusedWindow->setDispatchingTimeout(
7865 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007866 mDispatcher->onWindowInfosChanged(
7867 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007868
7869 tapOnFocusedWindow();
7870 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007871 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007872 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7873 mFocusedWindow->getDispatchingTimeout(
7874 DISPATCHING_TIMEOUT)),
7875 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7876
7877 ASSERT_THAT(anrConnectionTokens,
7878 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7879 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007880
7881 ASSERT_TRUE(mDispatcher->waitForIdle());
7882 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007883
7884 mFocusedWindow->consumeMotionDown();
7885 mFocusedWindow->consumeMotionUp();
7886 mUnfocusedWindow->consumeMotionOutside();
7887
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007888 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7889 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007890
7891 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007892 ASSERT_THAT(responsiveTokens,
7893 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7894 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007895 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007896}
7897
7898// If a window is already not responding, the second tap on the same window should be ignored.
7899// We should also log an error to account for the dropped event (not tested here).
7900// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7901TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7902 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007903 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007904 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007905 // Receive the events, but don't respond
7906 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7907 ASSERT_TRUE(downEventSequenceNum);
7908 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7909 ASSERT_TRUE(upEventSequenceNum);
7910 const std::chrono::duration timeout =
7911 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007912 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007913
7914 // Tap once again
7915 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007916 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007917 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007918 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007919 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007920 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007921 FOCUSED_WINDOW_LOCATION));
7922 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7923 // valid touch target
7924 mUnfocusedWindow->assertNoEvents();
7925
7926 // Consume the first tap
7927 mFocusedWindow->finishEvent(*downEventSequenceNum);
7928 mFocusedWindow->finishEvent(*upEventSequenceNum);
7929 ASSERT_TRUE(mDispatcher->waitForIdle());
7930 // The second tap did not go to the focused window
7931 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007932 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007933 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7934 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007935 mFakePolicy->assertNotifyAnrWasNotCalled();
7936}
7937
7938// If you tap outside of all windows, there will not be ANR
7939TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007940 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007941 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942 LOCATION_OUTSIDE_ALL_WINDOWS));
7943 ASSERT_TRUE(mDispatcher->waitForIdle());
7944 mFakePolicy->assertNotifyAnrWasNotCalled();
7945}
7946
7947// Since the focused window is paused, tapping on it should not produce any events
7948TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7949 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007950 mDispatcher->onWindowInfosChanged(
7951 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007952
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007953 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007954 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007955 FOCUSED_WINDOW_LOCATION));
7956
7957 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7958 ASSERT_TRUE(mDispatcher->waitForIdle());
7959 // Should not ANR because the window is paused, and touches shouldn't go to it
7960 mFakePolicy->assertNotifyAnrWasNotCalled();
7961
7962 mFocusedWindow->assertNoEvents();
7963 mUnfocusedWindow->assertNoEvents();
7964}
7965
7966/**
7967 * 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 -07007968 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007969 * If a different window becomes focused at this time, the key should go to that window instead.
7970 *
7971 * Warning!!!
7972 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7973 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007974 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007975 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7976 *
7977 * If that value changes, this test should also change.
7978 */
7979TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7980 // Set a long ANR timeout to prevent it from triggering
7981 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007982 mDispatcher->onWindowInfosChanged(
7983 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007984
7985 tapOnUnfocusedWindow();
7986 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7987 ASSERT_TRUE(downSequenceNum);
7988 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7989 ASSERT_TRUE(upSequenceNum);
7990 // Don't finish the events yet, and send a key
7991 // Injection will succeed because we will eventually give up and send the key to the focused
7992 // window even if motions are still being processed.
7993
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007994 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007995 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7996 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007998 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007999 // and the key remains pending, waiting for the touch events to be processed.
8000 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8001 // under the hood.
8002 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8003 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008004
8005 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008006 mFocusedWindow->setFocusable(false);
8007 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008008 mDispatcher->onWindowInfosChanged(
8009 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008010 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008011
8012 // Focus events should precede the key events
8013 mUnfocusedWindow->consumeFocusEvent(true);
8014 mFocusedWindow->consumeFocusEvent(false);
8015
8016 // Finish the tap events, which should unblock dispatcher
8017 mUnfocusedWindow->finishEvent(*downSequenceNum);
8018 mUnfocusedWindow->finishEvent(*upSequenceNum);
8019
8020 // Now that all queues are cleared and no backlog in the connections, the key event
8021 // can finally go to the newly focused "mUnfocusedWindow".
8022 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8023 mFocusedWindow->assertNoEvents();
8024 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008025 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026}
8027
8028// When the touch stream is split across 2 windows, and one of them does not respond,
8029// then ANR should be raised and the touch should be canceled for the unresponsive window.
8030// The other window should not be affected by that.
8031TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8032 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008033 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8034 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8035 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008036 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008037 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008038
8039 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008040 mDispatcher->notifyMotion(
8041 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8042 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008043
8044 const std::chrono::duration timeout =
8045 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008046 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008047
8048 mUnfocusedWindow->consumeMotionDown();
8049 mFocusedWindow->consumeMotionDown();
8050 // Focused window may or may not receive ACTION_MOVE
8051 // But it should definitely receive ACTION_CANCEL due to the ANR
8052 InputEvent* event;
8053 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8054 ASSERT_TRUE(moveOrCancelSequenceNum);
8055 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8056 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008057 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008058 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8059 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8060 mFocusedWindow->consumeMotionCancel();
8061 } else {
8062 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8063 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008064 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008065 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8066 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008067
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008068 mUnfocusedWindow->assertNoEvents();
8069 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008070 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008071}
8072
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008073/**
8074 * If we have no focused window, and a key comes in, we start the ANR timer.
8075 * The focused application should add a focused window before the timer runs out to prevent ANR.
8076 *
8077 * If the user touches another application during this time, the key should be dropped.
8078 * Next, if a new focused window comes in, without toggling the focused application,
8079 * then no ANR should occur.
8080 *
8081 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8082 * but in some cases the policy may not update the focused application.
8083 */
8084TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8085 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8086 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008087 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008088 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8089 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8090 mFocusedWindow->setFocusable(false);
8091
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008092 mDispatcher->onWindowInfosChanged(
8093 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008094 mFocusedWindow->consumeFocusEvent(false);
8095
8096 // Send a key. The ANR timer should start because there is no focused window.
8097 // 'focusedApplication' will get blamed if this timer completes.
8098 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008099 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008100 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8101 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008102 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008104
8105 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8106 // then the injected touches won't cause the focused event to get dropped.
8107 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8108 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8109 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8110 // For this test, it means that the key would get delivered to the window once it becomes
8111 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008112 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008113
8114 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008115 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8116 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8117 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008118
8119 // We do not consume the motion right away, because that would require dispatcher to first
8120 // process (== drop) the key event, and by that time, ANR will be raised.
8121 // Set the focused window first.
8122 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008123 mDispatcher->onWindowInfosChanged(
8124 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008125 setFocusedWindow(mFocusedWindow);
8126 mFocusedWindow->consumeFocusEvent(true);
8127 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8128 // to another application. This could be a bug / behaviour in the policy.
8129
8130 mUnfocusedWindow->consumeMotionDown();
8131
8132 ASSERT_TRUE(mDispatcher->waitForIdle());
8133 // Should not ANR because we actually have a focused window. It was just added too slowly.
8134 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8135}
8136
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008137// These tests ensure we cannot send touch events to a window that's positioned behind a window
8138// that has feature NO_INPUT_CHANNEL.
8139// Layout:
8140// Top (closest to user)
8141// mNoInputWindow (above all windows)
8142// mBottomWindow
8143// Bottom (furthest from user)
8144class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8145 virtual void SetUp() override {
8146 InputDispatcherTest::SetUp();
8147
8148 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008149 mNoInputWindow =
8150 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8151 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008152 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008153 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008154 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8155 // It's perfectly valid for this window to not have an associated input channel
8156
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008157 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8158 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008159 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8160
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008161 mDispatcher->onWindowInfosChanged(
8162 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008163 }
8164
8165protected:
8166 std::shared_ptr<FakeApplicationHandle> mApplication;
8167 sp<FakeWindowHandle> mNoInputWindow;
8168 sp<FakeWindowHandle> mBottomWindow;
8169};
8170
8171TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8172 PointF touchedPoint = {10, 10};
8173
Prabir Pradhan678438e2023-04-13 19:32:51 +00008174 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8175 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8176 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008177
8178 mNoInputWindow->assertNoEvents();
8179 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8180 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8181 // and therefore should prevent mBottomWindow from receiving touches
8182 mBottomWindow->assertNoEvents();
8183}
8184
8185/**
8186 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8187 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8188 */
8189TEST_F(InputDispatcherMultiWindowOcclusionTests,
8190 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008191 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8192 "Window with input channel and NO_INPUT_CHANNEL",
8193 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008194
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008195 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008196 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008197 mDispatcher->onWindowInfosChanged(
8198 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008199
8200 PointF touchedPoint = {10, 10};
8201
Prabir Pradhan678438e2023-04-13 19:32:51 +00008202 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8203 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8204 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008205
8206 mNoInputWindow->assertNoEvents();
8207 mBottomWindow->assertNoEvents();
8208}
8209
Vishnu Nair958da932020-08-21 17:12:37 -07008210class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8211protected:
8212 std::shared_ptr<FakeApplicationHandle> mApp;
8213 sp<FakeWindowHandle> mWindow;
8214 sp<FakeWindowHandle> mMirror;
8215
8216 virtual void SetUp() override {
8217 InputDispatcherTest::SetUp();
8218 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008219 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8220 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8221 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008222 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8223 mWindow->setFocusable(true);
8224 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008225 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008226 }
8227};
8228
8229TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8230 // Request focus on a mirrored window
8231 setFocusedWindow(mMirror);
8232
8233 // window gets focused
8234 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008236 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008237 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8238}
8239
8240// A focused & mirrored window remains focused only if the window and its mirror are both
8241// focusable.
8242TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8243 setFocusedWindow(mMirror);
8244
8245 // window gets focused
8246 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008248 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008249 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008251 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008252 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8253
8254 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008255 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008256
8257 // window loses focus since one of the windows associated with the token in not focusable
8258 mWindow->consumeFocusEvent(false);
8259
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008260 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008261 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008262 mWindow->assertNoEvents();
8263}
8264
8265// A focused & mirrored window remains focused until the window and its mirror both become
8266// invisible.
8267TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8268 setFocusedWindow(mMirror);
8269
8270 // window gets focused
8271 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008273 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008274 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008276 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008277 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8278
8279 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008280 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008281
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008283 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008284 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008286 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008287 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8288
8289 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008290 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008291
8292 // window loses focus only after all windows associated with the token become invisible.
8293 mWindow->consumeFocusEvent(false);
8294
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008295 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008296 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008297 mWindow->assertNoEvents();
8298}
8299
8300// A focused & mirrored window remains focused until both windows are removed.
8301TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8302 setFocusedWindow(mMirror);
8303
8304 // window gets focused
8305 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008307 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008308 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008310 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008311 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8312
8313 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008314 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008315
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008317 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008318 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008320 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008321 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8322
8323 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008324 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008325 mWindow->consumeFocusEvent(false);
8326
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008327 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008328 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008329 mWindow->assertNoEvents();
8330}
8331
8332// Focus request can be pending until one window becomes visible.
8333TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8334 // Request focus on an invisible mirror.
8335 mWindow->setVisible(false);
8336 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008337 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008338 setFocusedWindow(mMirror);
8339
8340 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008342 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8343 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008344
8345 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008346 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008347
8348 // window gets focused
8349 mWindow->consumeFocusEvent(true);
8350 // window gets the pending key event
8351 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8352}
Prabir Pradhan99987712020-11-10 18:43:05 -08008353
8354class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8355protected:
8356 std::shared_ptr<FakeApplicationHandle> mApp;
8357 sp<FakeWindowHandle> mWindow;
8358 sp<FakeWindowHandle> mSecondWindow;
8359
8360 void SetUp() override {
8361 InputDispatcherTest::SetUp();
8362 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008363 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008364 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008365 mSecondWindow =
8366 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008367 mSecondWindow->setFocusable(true);
8368
8369 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008370 mDispatcher->onWindowInfosChanged(
8371 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008372
8373 setFocusedWindow(mWindow);
8374 mWindow->consumeFocusEvent(true);
8375 }
8376
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008377 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008378 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008379 }
8380
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008381 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8382 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008383 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008384 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8385 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008386 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008387 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008388 }
8389};
8390
8391TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8392 // Ensure that capture cannot be obtained for unfocused windows.
8393 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8394 mFakePolicy->assertSetPointerCaptureNotCalled();
8395 mSecondWindow->assertNoEvents();
8396
8397 // Ensure that capture can be enabled from the focus window.
8398 requestAndVerifyPointerCapture(mWindow, true);
8399
8400 // Ensure that capture cannot be disabled from a window that does not have capture.
8401 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8402 mFakePolicy->assertSetPointerCaptureNotCalled();
8403
8404 // Ensure that capture can be disabled from the window with capture.
8405 requestAndVerifyPointerCapture(mWindow, false);
8406}
8407
8408TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008409 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008410
8411 setFocusedWindow(mSecondWindow);
8412
8413 // Ensure that the capture disabled event was sent first.
8414 mWindow->consumeCaptureEvent(false);
8415 mWindow->consumeFocusEvent(false);
8416 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008417 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008418
8419 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008420 notifyPointerCaptureChanged({});
8421 notifyPointerCaptureChanged(request);
8422 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008423 mWindow->assertNoEvents();
8424 mSecondWindow->assertNoEvents();
8425 mFakePolicy->assertSetPointerCaptureNotCalled();
8426}
8427
8428TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008429 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008430
8431 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008432 notifyPointerCaptureChanged({});
8433 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008434
8435 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008436 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008437 mWindow->consumeCaptureEvent(false);
8438 mWindow->assertNoEvents();
8439}
8440
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008441TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8442 requestAndVerifyPointerCapture(mWindow, true);
8443
8444 // The first window loses focus.
8445 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008446 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008447 mWindow->consumeCaptureEvent(false);
8448
8449 // Request Pointer Capture from the second window before the notification from InputReader
8450 // arrives.
8451 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008452 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008453
8454 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008455 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008456
8457 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008458 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008459
8460 mSecondWindow->consumeFocusEvent(true);
8461 mSecondWindow->consumeCaptureEvent(true);
8462}
8463
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008464TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8465 // App repeatedly enables and disables capture.
8466 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8467 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8468 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8469 mFakePolicy->assertSetPointerCaptureCalled(false);
8470 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8471 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8472
8473 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8474 // first request is now stale, this should do nothing.
8475 notifyPointerCaptureChanged(firstRequest);
8476 mWindow->assertNoEvents();
8477
8478 // InputReader notifies that the second request was enabled.
8479 notifyPointerCaptureChanged(secondRequest);
8480 mWindow->consumeCaptureEvent(true);
8481}
8482
Prabir Pradhan7092e262022-05-03 16:51:09 +00008483TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8484 requestAndVerifyPointerCapture(mWindow, true);
8485
8486 // App toggles pointer capture off and on.
8487 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8488 mFakePolicy->assertSetPointerCaptureCalled(false);
8489
8490 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8491 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8492
8493 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8494 // preceding "disable" request.
8495 notifyPointerCaptureChanged(enableRequest);
8496
8497 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8498 // any notifications.
8499 mWindow->assertNoEvents();
8500}
8501
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008502/**
8503 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8504 * mouse movements don't affect the previous mouse hovering state.
8505 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8506 * HOVER_MOVE events).
8507 */
8508TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8509 // Mouse hover on the window
8510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8511 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8512 .build());
8513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8514 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8515 .build());
8516
8517 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8518 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8519
8520 // Start pointer capture
8521 requestAndVerifyPointerCapture(mWindow, true);
8522
8523 // Send some relative mouse movements and receive them in the window.
8524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8526 .build());
8527 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8528 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8529
8530 // Stop pointer capture
8531 requestAndVerifyPointerCapture(mWindow, false);
8532
8533 // Continue hovering on the window
8534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8535 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8536 .build());
8537 mWindow->consumeMotionEvent(
8538 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8539
8540 mWindow->assertNoEvents();
8541}
8542
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008543class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8544protected:
8545 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008546
8547 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8548 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8549
8550 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8551 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8552
8553 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8554 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8555 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8556 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8557 MAXIMUM_OBSCURING_OPACITY);
8558
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008559 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8560 static constexpr gui::Uid APP_B_UID{10002};
8561 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008562
8563 sp<FakeWindowHandle> mTouchWindow;
8564
8565 virtual void SetUp() override {
8566 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008567 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008568 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8569 }
8570
8571 virtual void TearDown() override {
8572 InputDispatcherTest::TearDown();
8573 mTouchWindow.clear();
8574 }
8575
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008576 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008577 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008578 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008579 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008580 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008581 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008582 return window;
8583 }
8584
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008585 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008586 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8587 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008588 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008589 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008590 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008591 return window;
8592 }
8593
8594 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8596 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8597 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008598 }
8599};
8600
8601TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008602 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008603 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008604 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008605
8606 touch();
8607
8608 mTouchWindow->assertNoEvents();
8609}
8610
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008611TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008612 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8613 const sp<FakeWindowHandle>& w =
8614 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008615 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008616
8617 touch();
8618
8619 mTouchWindow->assertNoEvents();
8620}
8621
8622TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008623 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8624 const sp<FakeWindowHandle>& w =
8625 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008626 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008627
8628 touch();
8629
8630 w->assertNoEvents();
8631}
8632
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008633TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008634 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008635 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008636
8637 touch();
8638
8639 mTouchWindow->consumeAnyMotionDown();
8640}
8641
8642TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008643 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008644 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008645 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008646 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008647
8648 touch({PointF{100, 100}});
8649
8650 mTouchWindow->consumeAnyMotionDown();
8651}
8652
8653TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008654 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008655 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008656 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008657
8658 touch();
8659
8660 mTouchWindow->consumeAnyMotionDown();
8661}
8662
8663TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8664 const sp<FakeWindowHandle>& w =
8665 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008666 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008667
8668 touch();
8669
8670 mTouchWindow->consumeAnyMotionDown();
8671}
8672
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008673TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8674 const sp<FakeWindowHandle>& w =
8675 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008676 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008677
8678 touch();
8679
8680 w->assertNoEvents();
8681}
8682
8683/**
8684 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8685 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8686 * window, the occluding window will still receive ACTION_OUTSIDE event.
8687 */
8688TEST_F(InputDispatcherUntrustedTouchesTest,
8689 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8690 const sp<FakeWindowHandle>& w =
8691 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008692 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008693 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008694
8695 touch();
8696
8697 w->consumeMotionOutside();
8698}
8699
8700TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8701 const sp<FakeWindowHandle>& w =
8702 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008703 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008704 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008705
8706 touch();
8707
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008708 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008709}
8710
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008711TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008712 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008713 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8714 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008715 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008716
8717 touch();
8718
8719 mTouchWindow->consumeAnyMotionDown();
8720}
8721
8722TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8723 const sp<FakeWindowHandle>& w =
8724 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8725 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008726 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008727
8728 touch();
8729
8730 mTouchWindow->consumeAnyMotionDown();
8731}
8732
8733TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008734 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008735 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8736 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008737 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008738
8739 touch();
8740
8741 mTouchWindow->assertNoEvents();
8742}
8743
8744TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8745 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8746 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008747 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8748 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008749 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008750 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8751 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008752 mDispatcher->onWindowInfosChanged(
8753 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008754
8755 touch();
8756
8757 mTouchWindow->assertNoEvents();
8758}
8759
8760TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8761 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8762 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008763 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8764 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008765 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008766 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8767 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008768 mDispatcher->onWindowInfosChanged(
8769 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008770
8771 touch();
8772
8773 mTouchWindow->consumeAnyMotionDown();
8774}
8775
8776TEST_F(InputDispatcherUntrustedTouchesTest,
8777 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8778 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008779 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8780 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008781 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008782 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8783 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008784 mDispatcher->onWindowInfosChanged(
8785 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008786
8787 touch();
8788
8789 mTouchWindow->consumeAnyMotionDown();
8790}
8791
8792TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8793 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008794 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8795 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008796 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008797 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8798 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008799 mDispatcher->onWindowInfosChanged(
8800 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008801
8802 touch();
8803
8804 mTouchWindow->assertNoEvents();
8805}
8806
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008807TEST_F(InputDispatcherUntrustedTouchesTest,
8808 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8809 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008810 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8811 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008812 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008813 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8814 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008815 mDispatcher->onWindowInfosChanged(
8816 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008817
8818 touch();
8819
8820 mTouchWindow->assertNoEvents();
8821}
8822
8823TEST_F(InputDispatcherUntrustedTouchesTest,
8824 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8825 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008826 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8827 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008828 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008829 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8830 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008831 mDispatcher->onWindowInfosChanged(
8832 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008833
8834 touch();
8835
8836 mTouchWindow->consumeAnyMotionDown();
8837}
8838
8839TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8840 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008841 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8842 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008843 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008844
8845 touch();
8846
8847 mTouchWindow->consumeAnyMotionDown();
8848}
8849
8850TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8851 const sp<FakeWindowHandle>& w =
8852 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008853 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008854
8855 touch();
8856
8857 mTouchWindow->consumeAnyMotionDown();
8858}
8859
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008860TEST_F(InputDispatcherUntrustedTouchesTest,
8861 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8862 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8863 const sp<FakeWindowHandle>& w =
8864 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008865 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008866
8867 touch();
8868
8869 mTouchWindow->assertNoEvents();
8870}
8871
8872TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8873 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8874 const sp<FakeWindowHandle>& w =
8875 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008876 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008877
8878 touch();
8879
8880 mTouchWindow->consumeAnyMotionDown();
8881}
8882
8883TEST_F(InputDispatcherUntrustedTouchesTest,
8884 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8885 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8886 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008887 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8888 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008889 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008890
8891 touch();
8892
8893 mTouchWindow->consumeAnyMotionDown();
8894}
8895
8896TEST_F(InputDispatcherUntrustedTouchesTest,
8897 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8898 const sp<FakeWindowHandle>& w1 =
8899 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8900 OPACITY_BELOW_THRESHOLD);
8901 const sp<FakeWindowHandle>& w2 =
8902 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8903 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008904 mDispatcher->onWindowInfosChanged(
8905 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008906
8907 touch();
8908
8909 mTouchWindow->assertNoEvents();
8910}
8911
8912/**
8913 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8914 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8915 * (which alone would result in allowing touches) does not affect the blocking behavior.
8916 */
8917TEST_F(InputDispatcherUntrustedTouchesTest,
8918 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8919 const sp<FakeWindowHandle>& wB =
8920 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8921 OPACITY_BELOW_THRESHOLD);
8922 const sp<FakeWindowHandle>& wC =
8923 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8924 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008925 mDispatcher->onWindowInfosChanged(
8926 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008927
8928 touch();
8929
8930 mTouchWindow->assertNoEvents();
8931}
8932
8933/**
8934 * This test is testing that a window from a different UID but with same application token doesn't
8935 * block the touch. Apps can share the application token for close UI collaboration for example.
8936 */
8937TEST_F(InputDispatcherUntrustedTouchesTest,
8938 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8939 const sp<FakeWindowHandle>& w =
8940 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8941 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008942 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008943
8944 touch();
8945
8946 mTouchWindow->consumeAnyMotionDown();
8947}
8948
arthurhungb89ccb02020-12-30 16:19:01 +08008949class InputDispatcherDragTests : public InputDispatcherTest {
8950protected:
8951 std::shared_ptr<FakeApplicationHandle> mApp;
8952 sp<FakeWindowHandle> mWindow;
8953 sp<FakeWindowHandle> mSecondWindow;
8954 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008955 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008956 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8957 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008958
8959 void SetUp() override {
8960 InputDispatcherTest::SetUp();
8961 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008962 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008963 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008964
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008965 mSecondWindow =
8966 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008967 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008968
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008969 mSpyWindow =
8970 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008971 mSpyWindow->setSpy(true);
8972 mSpyWindow->setTrustedOverlay(true);
8973 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8974
arthurhungb89ccb02020-12-30 16:19:01 +08008975 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008976 mDispatcher->onWindowInfosChanged(
8977 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8978 {},
8979 0,
8980 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008981 }
8982
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008983 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8984 switch (fromSource) {
8985 case AINPUT_SOURCE_TOUCHSCREEN:
8986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008987 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008988 ADISPLAY_ID_DEFAULT, {50, 50}))
8989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8990 break;
8991 case AINPUT_SOURCE_STYLUS:
8992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008993 injectMotionEvent(*mDispatcher,
8994 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8995 AINPUT_SOURCE_STYLUS)
8996 .buttonState(
8997 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8998 .pointer(PointerBuilder(0, ToolType::STYLUS)
8999 .x(50)
9000 .y(50))
9001 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009002 break;
9003 case AINPUT_SOURCE_MOUSE:
9004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009005 injectMotionEvent(*mDispatcher,
9006 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9007 AINPUT_SOURCE_MOUSE)
9008 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9009 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9010 ToolType::MOUSE)
9011 .x(50)
9012 .y(50))
9013 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009014 break;
9015 default:
9016 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9017 }
arthurhungb89ccb02020-12-30 16:19:01 +08009018
9019 // Window should receive motion event.
9020 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009021 // Spy window should also receive motion event
9022 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009023 }
9024
9025 // Start performing drag, we will create a drag window and transfer touch to it.
9026 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9027 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009028 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009029 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009030 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009031 }
arthurhungb89ccb02020-12-30 16:19:01 +08009032
9033 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009034 mDragWindow =
9035 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009036 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009037 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9038 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9039 {},
9040 0,
9041 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009042
9043 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009044 bool transferred =
9045 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009046 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009047 if (transferred) {
9048 mWindow->consumeMotionCancel();
9049 mDragWindow->consumeMotionDown();
9050 }
9051 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009052 }
9053};
9054
9055TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009056 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009057
9058 // Move on window.
9059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009060 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009061 ADISPLAY_ID_DEFAULT, {50, 50}))
9062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9063 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9064 mWindow->consumeDragEvent(false, 50, 50);
9065 mSecondWindow->assertNoEvents();
9066
9067 // Move to another window.
9068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009069 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009070 ADISPLAY_ID_DEFAULT, {150, 50}))
9071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9072 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9073 mWindow->consumeDragEvent(true, 150, 50);
9074 mSecondWindow->consumeDragEvent(false, 50, 50);
9075
9076 // Move back to original window.
9077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009078 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009079 ADISPLAY_ID_DEFAULT, {50, 50}))
9080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9081 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9082 mWindow->consumeDragEvent(false, 50, 50);
9083 mSecondWindow->consumeDragEvent(true, -50, 50);
9084
9085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009086 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9087 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9089 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9090 mWindow->assertNoEvents();
9091 mSecondWindow->assertNoEvents();
9092}
9093
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009094TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009095 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009096
9097 // No cancel event after drag start
9098 mSpyWindow->assertNoEvents();
9099
9100 const MotionEvent secondFingerDownEvent =
9101 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9102 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009103 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9104 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009105 .build();
9106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009107 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009108 InputEventInjectionSync::WAIT_FOR_RESULT))
9109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9110
9111 // Receives cancel for first pointer after next pointer down
9112 mSpyWindow->consumeMotionCancel();
9113 mSpyWindow->consumeMotionDown();
9114
9115 mSpyWindow->assertNoEvents();
9116}
9117
arthurhungf452d0b2021-01-06 00:19:52 +08009118TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009119 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009120
9121 // Move on window.
9122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009123 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009124 ADISPLAY_ID_DEFAULT, {50, 50}))
9125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9126 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9127 mWindow->consumeDragEvent(false, 50, 50);
9128 mSecondWindow->assertNoEvents();
9129
9130 // Move to another window.
9131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009132 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009133 ADISPLAY_ID_DEFAULT, {150, 50}))
9134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9135 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9136 mWindow->consumeDragEvent(true, 150, 50);
9137 mSecondWindow->consumeDragEvent(false, 50, 50);
9138
9139 // drop to another window.
9140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009141 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009142 {150, 50}))
9143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9144 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009145 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009146 mWindow->assertNoEvents();
9147 mSecondWindow->assertNoEvents();
9148}
9149
arthurhung6d4bed92021-03-17 11:59:33 +08009150TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009151 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009152
9153 // Move on window and keep button pressed.
9154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009155 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009156 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9157 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009158 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009159 .build()))
9160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9161 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9162 mWindow->consumeDragEvent(false, 50, 50);
9163 mSecondWindow->assertNoEvents();
9164
9165 // Move to another window and release button, expect to drop item.
9166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009167 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009168 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9169 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009171 .build()))
9172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9173 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9174 mWindow->assertNoEvents();
9175 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009176 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009177
9178 // nothing to the window.
9179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009180 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009181 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9182 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009183 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009184 .build()))
9185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9186 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9187 mWindow->assertNoEvents();
9188 mSecondWindow->assertNoEvents();
9189}
9190
Arthur Hung54745652022-04-20 07:17:41 +00009191TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009192 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009193
9194 // Set second window invisible.
9195 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009196 mDispatcher->onWindowInfosChanged(
9197 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009198
9199 // Move on window.
9200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009201 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009202 ADISPLAY_ID_DEFAULT, {50, 50}))
9203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9204 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9205 mWindow->consumeDragEvent(false, 50, 50);
9206 mSecondWindow->assertNoEvents();
9207
9208 // Move to another window.
9209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009210 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009211 ADISPLAY_ID_DEFAULT, {150, 50}))
9212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9213 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9214 mWindow->consumeDragEvent(true, 150, 50);
9215 mSecondWindow->assertNoEvents();
9216
9217 // drop to another window.
9218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009219 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009220 {150, 50}))
9221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9222 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009223 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009224 mWindow->assertNoEvents();
9225 mSecondWindow->assertNoEvents();
9226}
9227
Arthur Hung54745652022-04-20 07:17:41 +00009228TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009229 // Ensure window could track pointerIds if it didn't support split touch.
9230 mWindow->setPreventSplitting(true);
9231
Arthur Hung54745652022-04-20 07:17:41 +00009232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009233 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009234 {50, 50}))
9235 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9236 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9237
9238 const MotionEvent secondFingerDownEvent =
9239 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9240 .displayId(ADISPLAY_ID_DEFAULT)
9241 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009242 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9243 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009244 .build();
9245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009246 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009247 InputEventInjectionSync::WAIT_FOR_RESULT))
9248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009249 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009250
9251 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009252 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009253}
9254
9255TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9256 // First down on second window.
9257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009259 {150, 50}))
9260 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9261
9262 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9263
9264 // Second down on first window.
9265 const MotionEvent secondFingerDownEvent =
9266 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9267 .displayId(ADISPLAY_ID_DEFAULT)
9268 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009269 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9270 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009271 .build();
9272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009273 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009274 InputEventInjectionSync::WAIT_FOR_RESULT))
9275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9276 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9277
9278 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009279 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009280
9281 // Move on window.
9282 const MotionEvent secondFingerMoveEvent =
9283 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9284 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009285 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9286 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009287 .build();
9288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009289 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009290 InputEventInjectionSync::WAIT_FOR_RESULT));
9291 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9292 mWindow->consumeDragEvent(false, 50, 50);
9293 mSecondWindow->consumeMotionMove();
9294
9295 // Release the drag pointer should perform drop.
9296 const MotionEvent secondFingerUpEvent =
9297 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9298 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009299 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9300 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009301 .build();
9302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009303 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009304 InputEventInjectionSync::WAIT_FOR_RESULT));
9305 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009306 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009307 mWindow->assertNoEvents();
9308 mSecondWindow->consumeMotionMove();
9309}
9310
Arthur Hung3915c1f2022-05-31 07:17:17 +00009311TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009312 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009313
9314 // Update window of second display.
9315 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009316 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009317 mDispatcher->onWindowInfosChanged(
9318 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9319 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9320 {},
9321 0,
9322 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009323
9324 // Let second display has a touch state.
9325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009326 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009327 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9328 AINPUT_SOURCE_TOUCHSCREEN)
9329 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009330 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009331 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009332 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009333 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009334 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009335 mDispatcher->onWindowInfosChanged(
9336 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9337 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9338 {},
9339 0,
9340 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009341
9342 // Move on window.
9343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009344 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009345 ADISPLAY_ID_DEFAULT, {50, 50}))
9346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9347 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9348 mWindow->consumeDragEvent(false, 50, 50);
9349 mSecondWindow->assertNoEvents();
9350
9351 // Move to another window.
9352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009353 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009354 ADISPLAY_ID_DEFAULT, {150, 50}))
9355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9356 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9357 mWindow->consumeDragEvent(true, 150, 50);
9358 mSecondWindow->consumeDragEvent(false, 50, 50);
9359
9360 // drop to another window.
9361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009362 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009363 {150, 50}))
9364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9365 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009366 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009367 mWindow->assertNoEvents();
9368 mSecondWindow->assertNoEvents();
9369}
9370
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009371TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9372 startDrag(true, AINPUT_SOURCE_MOUSE);
9373 // Move on window.
9374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009375 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009376 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9377 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009378 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009379 .x(50)
9380 .y(50))
9381 .build()))
9382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9383 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9384 mWindow->consumeDragEvent(false, 50, 50);
9385 mSecondWindow->assertNoEvents();
9386
9387 // Move to another window.
9388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009389 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009390 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9391 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009392 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009393 .x(150)
9394 .y(50))
9395 .build()))
9396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9397 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9398 mWindow->consumeDragEvent(true, 150, 50);
9399 mSecondWindow->consumeDragEvent(false, 50, 50);
9400
9401 // drop to another window.
9402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009403 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009404 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9405 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009406 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009407 .x(150)
9408 .y(50))
9409 .build()))
9410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9411 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009412 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009413 mWindow->assertNoEvents();
9414 mSecondWindow->assertNoEvents();
9415}
9416
Linnan Li5af92f92023-07-14 14:36:22 +08009417/**
9418 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9419 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9420 */
9421TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9422 // Down on second window
9423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9424 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9425 {150, 50}))
9426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9427
9428 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9429 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9430
9431 // Down on first window
9432 const MotionEvent secondFingerDownEvent =
9433 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9434 .displayId(ADISPLAY_ID_DEFAULT)
9435 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9436 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9437 .build();
9438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9439 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9440 InputEventInjectionSync::WAIT_FOR_RESULT))
9441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9442 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9443 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9444 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9445
9446 // Start drag on first window
9447 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9448
9449 // Trigger cancel
9450 mDispatcher->cancelCurrentTouch();
9451 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9452 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9453 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9454
9455 ASSERT_TRUE(mDispatcher->waitForIdle());
9456 // The D&D finished with nullptr
9457 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9458
9459 // Remove drag window
9460 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9461
9462 // Inject a simple gesture, ensure dispatcher not crashed
9463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9464 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9465 PointF{50, 50}))
9466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9467 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9468
9469 const MotionEvent moveEvent =
9470 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9471 .displayId(ADISPLAY_ID_DEFAULT)
9472 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9473 .build();
9474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9475 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9476 InputEventInjectionSync::WAIT_FOR_RESULT))
9477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9478 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9479
9480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9481 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9482 {50, 50}))
9483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9484 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9485}
9486
Vishnu Nair062a8672021-09-03 16:07:44 -07009487class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9488
9489TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009491 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9492 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009493 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9495 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009496 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009497 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009498 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009499
9500 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009501 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009502 window->assertNoEvents();
9503
Prabir Pradhan678438e2023-04-13 19:32:51 +00009504 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9505 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009506 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9507 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009508 window->assertNoEvents();
9509
9510 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009511 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009512 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009513
Prabir Pradhan678438e2023-04-13 19:32:51 +00009514 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009515 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9516
Prabir Pradhan678438e2023-04-13 19:32:51 +00009517 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9518 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009519 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9520 window->assertNoEvents();
9521}
9522
9523TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9524 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9525 std::make_shared<FakeApplicationHandle>();
9526 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009527 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9528 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009529 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009530 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009531 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009533 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9534 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009535 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009536 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009537 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9538 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009539 mDispatcher->onWindowInfosChanged(
9540 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009541 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009542 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009543
9544 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009545 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009546 window->assertNoEvents();
9547
Prabir Pradhan678438e2023-04-13 19:32:51 +00009548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9549 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009550 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9551 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009552 window->assertNoEvents();
9553
9554 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009555 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009556 mDispatcher->onWindowInfosChanged(
9557 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009558
Prabir Pradhan678438e2023-04-13 19:32:51 +00009559 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009560 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9561
Prabir Pradhan678438e2023-04-13 19:32:51 +00009562 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9563 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009564 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9565 window->assertNoEvents();
9566}
9567
9568TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9569 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9570 std::make_shared<FakeApplicationHandle>();
9571 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009572 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9573 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009574 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009575 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009576 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009578 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9579 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009580 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009581 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009582 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9583 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009584 mDispatcher->onWindowInfosChanged(
9585 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009586 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009587 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009588
9589 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009590 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009591 window->assertNoEvents();
9592
Prabir Pradhan678438e2023-04-13 19:32:51 +00009593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9594 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9596 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009597 window->assertNoEvents();
9598
9599 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009600 mDispatcher->onWindowInfosChanged(
9601 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009602
Prabir Pradhan678438e2023-04-13 19:32:51 +00009603 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009604 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9605
Prabir Pradhan678438e2023-04-13 19:32:51 +00009606 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9607 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009608 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9609 window->assertNoEvents();
9610}
9611
Antonio Kantekf16f2832021-09-28 04:39:20 +00009612class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9613protected:
9614 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009615 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009616 sp<FakeWindowHandle> mWindow;
9617 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009618 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009619
9620 void SetUp() override {
9621 InputDispatcherTest::SetUp();
9622
9623 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009624 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009625 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009626 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009627 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009628 mSecondWindow =
9629 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009630 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009631 mThirdWindow =
9632 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9633 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9634 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009635
9636 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009637 mDispatcher->onWindowInfosChanged(
9638 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9639 {},
9640 0,
9641 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009642 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009643 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009644
Antonio Kantek15beb512022-06-13 22:35:41 +00009645 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009646 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009647 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009648 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9649 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009650 mThirdWindow->assertNoEvents();
9651 }
9652
9653 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9654 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009655 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009656 SECOND_DISPLAY_ID)) {
9657 mWindow->assertNoEvents();
9658 mSecondWindow->assertNoEvents();
9659 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009660 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009661 }
9662
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009663 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009664 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009665 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9666 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009667 mWindow->consumeTouchModeEvent(inTouchMode);
9668 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009669 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009670 }
9671};
9672
Antonio Kantek26defcf2022-02-08 01:12:27 +00009673TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009674 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009675 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9676 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009677 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009678}
9679
Antonio Kantek26defcf2022-02-08 01:12:27 +00009680TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9681 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009682 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009683 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009684 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009685 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009686 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009687 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009688 mWindow->assertNoEvents();
9689 mSecondWindow->assertNoEvents();
9690}
9691
9692TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9693 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009694 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009695 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009696 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009697 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009698 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009699}
9700
Antonio Kantekf16f2832021-09-28 04:39:20 +00009701TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009702 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009703 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9704 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009705 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009706 mWindow->assertNoEvents();
9707 mSecondWindow->assertNoEvents();
9708}
9709
Antonio Kantek15beb512022-06-13 22:35:41 +00009710TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9711 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9712 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9713 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009714 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009715 mWindow->assertNoEvents();
9716 mSecondWindow->assertNoEvents();
9717 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9718}
9719
Antonio Kantek48710e42022-03-24 14:19:30 -07009720TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9721 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9723 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009724 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9725 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9726
9727 // Then remove focus.
9728 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009729 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009730
9731 // Assert that caller can switch touch mode by owning one of the last interacted window.
9732 const WindowInfo& windowInfo = *mWindow->getInfo();
9733 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9734 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009735 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009736}
9737
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009738class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9739public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009740 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009741 std::shared_ptr<FakeApplicationHandle> application =
9742 std::make_shared<FakeApplicationHandle>();
9743 std::string name = "Fake Spy ";
9744 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009745 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9746 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009747 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009748 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009749 return spy;
9750 }
9751
9752 sp<FakeWindowHandle> createForeground() {
9753 std::shared_ptr<FakeApplicationHandle> application =
9754 std::make_shared<FakeApplicationHandle>();
9755 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009756 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9757 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009758 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009759 return window;
9760 }
9761
9762private:
9763 int mSpyCount{0};
9764};
9765
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009766using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009767/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009768 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9769 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009770TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009771 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009772 ScopedSilentDeath _silentDeath;
9773
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009774 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009775 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009776 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009777 ".* not a trusted overlay");
9778}
9779
9780/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009781 * Input injection into a display with a spy window but no foreground windows should succeed.
9782 */
9783TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009784 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009785 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009786
9787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009788 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9790 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9791}
9792
9793/**
9794 * Verify the order in which different input windows receive events. The touched foreground window
9795 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9796 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9797 * receive events before ones belows it.
9798 *
9799 * Here, we set up a scenario with four windows in the following Z order from the top:
9800 * spy1, spy2, window, spy3.
9801 * We then inject an event and verify that the foreground "window" receives it first, followed by
9802 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9803 * window.
9804 */
9805TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9806 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009807 auto spy1 = createSpy();
9808 auto spy2 = createSpy();
9809 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009810 mDispatcher->onWindowInfosChanged(
9811 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009812 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9813 const size_t numChannels = channels.size();
9814
Michael Wright8e9a8562022-02-09 13:44:29 +00009815 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009816 if (!epollFd.ok()) {
9817 FAIL() << "Failed to create epoll fd";
9818 }
9819
9820 for (size_t i = 0; i < numChannels; i++) {
9821 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9822 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9823 FAIL() << "Failed to add fd to epoll";
9824 }
9825 }
9826
9827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009829 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9830
9831 std::vector<size_t> eventOrder;
9832 std::vector<struct epoll_event> events(numChannels);
9833 for (;;) {
9834 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9835 (100ms).count());
9836 if (nFds < 0) {
9837 FAIL() << "Failed to call epoll_wait";
9838 }
9839 if (nFds == 0) {
9840 break; // epoll_wait timed out
9841 }
9842 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009843 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009844 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009845 channels[i]->consumeMotionDown();
9846 }
9847 }
9848
9849 // Verify the order in which the events were received.
9850 EXPECT_EQ(3u, eventOrder.size());
9851 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9852 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9853 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9854}
9855
9856/**
9857 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9858 */
9859TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9860 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009861 auto spy = createSpy();
9862 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009863 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009864
9865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009866 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9868 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9869 spy->assertNoEvents();
9870}
9871
9872/**
9873 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9874 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9875 * to the window.
9876 */
9877TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9878 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009879 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009880 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009881 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009882
9883 // Inject an event outside the spy window's touchable region.
9884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009885 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9887 window->consumeMotionDown();
9888 spy->assertNoEvents();
9889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009890 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9892 window->consumeMotionUp();
9893 spy->assertNoEvents();
9894
9895 // Inject an event inside the spy window's touchable region.
9896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009897 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009898 {5, 10}))
9899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9900 window->consumeMotionDown();
9901 spy->consumeMotionDown();
9902}
9903
9904/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009905 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009906 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009907 */
9908TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9909 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009910 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009911 auto spy = createSpy();
9912 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009913 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009914 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009915 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009916
9917 // Inject an event outside the spy window's frame and touchable region.
9918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009920 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9922 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009923 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009924}
9925
9926/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009927 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9928 * pointers that are down within its bounds.
9929 */
9930TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9931 auto windowLeft = createForeground();
9932 windowLeft->setFrame({0, 0, 100, 200});
9933 auto windowRight = createForeground();
9934 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009935 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009936 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009937 mDispatcher->onWindowInfosChanged(
9938 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009939
9940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009941 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009942 {50, 50}))
9943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9944 windowLeft->consumeMotionDown();
9945 spy->consumeMotionDown();
9946
9947 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009948 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009949 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009950 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9951 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009952 .build();
9953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009954 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009955 InputEventInjectionSync::WAIT_FOR_RESULT))
9956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9957 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009958 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009959}
9960
9961/**
9962 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9963 * the spy should receive the second pointer with ACTION_DOWN.
9964 */
9965TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9966 auto window = createForeground();
9967 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009968 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009969 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009970 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009971
9972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009973 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009974 {50, 50}))
9975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9976 window->consumeMotionDown();
9977 spyRight->assertNoEvents();
9978
9979 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009980 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009981 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009982 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9983 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009984 .build();
9985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009986 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009987 InputEventInjectionSync::WAIT_FOR_RESULT))
9988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009989 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009990 spyRight->consumeMotionDown();
9991}
9992
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009993/**
9994 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9995 * windows should be allowed to control split touch.
9996 */
9997TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009998 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009999 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010000 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010001 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010002
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010003 auto window = createForeground();
10004 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010005
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010006 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010007
10008 // First finger down, no window touched.
10009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010010 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010011 {100, 200}))
10012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10013 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10014 window->assertNoEvents();
10015
10016 // Second finger down on window, the window should receive touch down.
10017 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010018 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010019 .displayId(ADISPLAY_ID_DEFAULT)
10020 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010021 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10022 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010023 .build();
10024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010025 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010026 InputEventInjectionSync::WAIT_FOR_RESULT))
10027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10028
10029 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010030 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010031}
10032
10033/**
10034 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10035 * do not receive key events.
10036 */
10037TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010038 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010039 spy->setFocusable(false);
10040
10041 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010042 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010043 setFocusedWindow(window);
10044 window->consumeFocusEvent(true);
10045
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010047 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10048 window->consumeKeyDown(ADISPLAY_ID_NONE);
10049
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010051 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10052 window->consumeKeyUp(ADISPLAY_ID_NONE);
10053
10054 spy->assertNoEvents();
10055}
10056
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010057using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10058
10059/**
10060 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10061 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10062 */
10063TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10064 auto window = createForeground();
10065 auto spy1 = createSpy();
10066 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010067 mDispatcher->onWindowInfosChanged(
10068 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010069
10070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010071 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10073 window->consumeMotionDown();
10074 spy1->consumeMotionDown();
10075 spy2->consumeMotionDown();
10076
10077 // Pilfer pointers from the second spy window.
10078 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10079 spy2->assertNoEvents();
10080 spy1->consumeMotionCancel();
10081 window->consumeMotionCancel();
10082
10083 // The rest of the gesture should only be sent to the second spy window.
10084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010085 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010086 ADISPLAY_ID_DEFAULT))
10087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10088 spy2->consumeMotionMove();
10089 spy1->assertNoEvents();
10090 window->assertNoEvents();
10091}
10092
10093/**
10094 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10095 * in the middle of the gesture.
10096 */
10097TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10098 auto window = createForeground();
10099 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010100 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010101
10102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010103 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10105 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10106 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10107
10108 window->releaseChannel();
10109
10110 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10111
10112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010113 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10115 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10116}
10117
10118/**
10119 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10120 * the spy, but not to any other windows.
10121 */
10122TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10123 auto spy = createSpy();
10124 auto window = createForeground();
10125
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010126 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010127
10128 // First finger down on the window and the spy.
10129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010130 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010131 {100, 200}))
10132 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10133 spy->consumeMotionDown();
10134 window->consumeMotionDown();
10135
10136 // Spy window pilfers the pointers.
10137 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10138 window->consumeMotionCancel();
10139
10140 // Second finger down on the window and spy, but the window should not receive the pointer down.
10141 const MotionEvent secondFingerDownEvent =
10142 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10143 .displayId(ADISPLAY_ID_DEFAULT)
10144 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010145 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10146 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010147 .build();
10148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010149 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010150 InputEventInjectionSync::WAIT_FOR_RESULT))
10151 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10152
Harry Cutts33476232023-01-30 19:57:29 +000010153 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010154
10155 // Third finger goes down outside all windows, so injection should fail.
10156 const MotionEvent thirdFingerDownEvent =
10157 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10158 .displayId(ADISPLAY_ID_DEFAULT)
10159 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010160 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10161 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10162 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010163 .build();
10164 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010165 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010166 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010167 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010168
10169 spy->assertNoEvents();
10170 window->assertNoEvents();
10171}
10172
10173/**
10174 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10175 */
10176TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10177 auto spy = createSpy();
10178 spy->setFrame(Rect(0, 0, 100, 100));
10179 auto window = createForeground();
10180 window->setFrame(Rect(0, 0, 200, 200));
10181
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010182 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010183
10184 // First finger down on the window only
10185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010186 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010187 {150, 150}))
10188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10189 window->consumeMotionDown();
10190
10191 // Second finger down on the spy and window
10192 const MotionEvent secondFingerDownEvent =
10193 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10194 .displayId(ADISPLAY_ID_DEFAULT)
10195 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010196 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10197 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010198 .build();
10199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010200 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010201 InputEventInjectionSync::WAIT_FOR_RESULT))
10202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10203 spy->consumeMotionDown();
10204 window->consumeMotionPointerDown(1);
10205
10206 // Third finger down on the spy and window
10207 const MotionEvent thirdFingerDownEvent =
10208 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10209 .displayId(ADISPLAY_ID_DEFAULT)
10210 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010211 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10212 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10213 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010214 .build();
10215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010216 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010217 InputEventInjectionSync::WAIT_FOR_RESULT))
10218 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10219 spy->consumeMotionPointerDown(1);
10220 window->consumeMotionPointerDown(2);
10221
10222 // Spy window pilfers the pointers.
10223 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010224 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10225 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010226
10227 spy->assertNoEvents();
10228 window->assertNoEvents();
10229}
10230
10231/**
10232 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10233 * other windows should be canceled. If this results in the cancellation of all pointers for some
10234 * window, then that window should receive ACTION_CANCEL.
10235 */
10236TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10237 auto spy = createSpy();
10238 spy->setFrame(Rect(0, 0, 100, 100));
10239 auto window = createForeground();
10240 window->setFrame(Rect(0, 0, 200, 200));
10241
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010242 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010243
10244 // First finger down on both spy and window
10245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010246 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010247 {10, 10}))
10248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10249 window->consumeMotionDown();
10250 spy->consumeMotionDown();
10251
10252 // Second finger down on the spy and window
10253 const MotionEvent secondFingerDownEvent =
10254 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10255 .displayId(ADISPLAY_ID_DEFAULT)
10256 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010257 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10258 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010259 .build();
10260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010261 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010262 InputEventInjectionSync::WAIT_FOR_RESULT))
10263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10264 spy->consumeMotionPointerDown(1);
10265 window->consumeMotionPointerDown(1);
10266
10267 // Spy window pilfers the pointers.
10268 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10269 window->consumeMotionCancel();
10270
10271 spy->assertNoEvents();
10272 window->assertNoEvents();
10273}
10274
10275/**
10276 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10277 * be sent to other windows
10278 */
10279TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10280 auto spy = createSpy();
10281 spy->setFrame(Rect(0, 0, 100, 100));
10282 auto window = createForeground();
10283 window->setFrame(Rect(0, 0, 200, 200));
10284
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010285 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010286
10287 // First finger down on both window and spy
10288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010289 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010290 {10, 10}))
10291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10292 window->consumeMotionDown();
10293 spy->consumeMotionDown();
10294
10295 // Spy window pilfers the pointers.
10296 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10297 window->consumeMotionCancel();
10298
10299 // Second finger down on the window only
10300 const MotionEvent secondFingerDownEvent =
10301 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10302 .displayId(ADISPLAY_ID_DEFAULT)
10303 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010304 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10305 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010306 .build();
10307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010308 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010309 InputEventInjectionSync::WAIT_FOR_RESULT))
10310 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10311 window->consumeMotionDown();
10312 window->assertNoEvents();
10313
10314 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10315 spy->consumeMotionMove();
10316 spy->assertNoEvents();
10317}
10318
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010319/**
10320 * A window on the left and a window on the right. Also, a spy window that's above all of the
10321 * windows, and spanning both left and right windows.
10322 * Send simultaneous motion streams from two different devices, one to the left window, and another
10323 * to the right window.
10324 * Pilfer from spy window.
10325 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10326 */
10327TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10328 sp<FakeWindowHandle> spy = createSpy();
10329 spy->setFrame(Rect(0, 0, 200, 200));
10330 sp<FakeWindowHandle> leftWindow = createForeground();
10331 leftWindow->setFrame(Rect(0, 0, 100, 100));
10332
10333 sp<FakeWindowHandle> rightWindow = createForeground();
10334 rightWindow->setFrame(Rect(100, 0, 200, 100));
10335
10336 constexpr int32_t stylusDeviceId = 1;
10337 constexpr int32_t touchDeviceId = 2;
10338
10339 mDispatcher->onWindowInfosChanged(
10340 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10341
10342 // Stylus down on left window and spy
10343 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10344 .deviceId(stylusDeviceId)
10345 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10346 .build());
10347 leftWindow->consumeMotionEvent(
10348 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10349 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10350
10351 // Finger down on right window and spy - but spy already has stylus
10352 mDispatcher->notifyMotion(
10353 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10354 .deviceId(touchDeviceId)
10355 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10356 .build());
10357 rightWindow->consumeMotionEvent(
10358 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10359 leftWindow->consumeMotionEvent(
10360 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10361 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10362 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10363
10364 // Act: pilfer from spy. Spy is currently receiving touch events.
10365 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10366 rightWindow->consumeMotionEvent(
10367 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10368
10369 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10370 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10371 .deviceId(stylusDeviceId)
10372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10373 .build());
10374 mDispatcher->notifyMotion(
10375 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10376 .deviceId(touchDeviceId)
10377 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10378 .build());
10379 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10380
10381 spy->assertNoEvents();
10382 leftWindow->assertNoEvents();
10383 rightWindow->assertNoEvents();
10384}
10385
Prabir Pradhand65552b2021-10-07 11:23:50 -070010386class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10387public:
10388 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10389 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10390 std::make_shared<FakeApplicationHandle>();
10391 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010392 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10393 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010394 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010395 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010396 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010397 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010398 overlay->setTrustedOverlay(true);
10399
10400 std::shared_ptr<FakeApplicationHandle> application =
10401 std::make_shared<FakeApplicationHandle>();
10402 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010403 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10404 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010405 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010406 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010407
10408 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010409 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010410 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010411 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010412 return {std::move(overlay), std::move(window)};
10413 }
10414
10415 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010416 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010417 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010418 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010419 }
10420
10421 void sendStylusEvent(int32_t action) {
10422 NotifyMotionArgs motionArgs =
10423 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10424 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010425 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010426 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010427 }
10428};
10429
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010430using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10431
10432TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010433 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010434 ScopedSilentDeath _silentDeath;
10435
Prabir Pradhand65552b2021-10-07 11:23:50 -070010436 auto [overlay, window] = setupStylusOverlayScenario();
10437 overlay->setTrustedOverlay(false);
10438 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010439 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10440 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010441 ".* not a trusted overlay");
10442}
10443
10444TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10445 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010446 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010447
10448 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10449 overlay->consumeMotionDown();
10450 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10451 overlay->consumeMotionUp();
10452
10453 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10454 window->consumeMotionDown();
10455 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10456 window->consumeMotionUp();
10457
10458 overlay->assertNoEvents();
10459 window->assertNoEvents();
10460}
10461
10462TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10463 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010464 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010465 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010466
10467 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10468 overlay->consumeMotionDown();
10469 window->consumeMotionDown();
10470 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10471 overlay->consumeMotionUp();
10472 window->consumeMotionUp();
10473
10474 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10475 window->consumeMotionDown();
10476 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10477 window->consumeMotionUp();
10478
10479 overlay->assertNoEvents();
10480 window->assertNoEvents();
10481}
10482
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010483/**
10484 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10485 * The scenario is as follows:
10486 * - The stylus interceptor overlay is configured as a spy window.
10487 * - The stylus interceptor spy receives the start of a new stylus gesture.
10488 * - It pilfers pointers and then configures itself to no longer be a spy.
10489 * - The stylus interceptor continues to receive the rest of the gesture.
10490 */
10491TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10492 auto [overlay, window] = setupStylusOverlayScenario();
10493 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010494 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010495
10496 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10497 overlay->consumeMotionDown();
10498 window->consumeMotionDown();
10499
10500 // The interceptor pilfers the pointers.
10501 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10502 window->consumeMotionCancel();
10503
10504 // The interceptor configures itself so that it is no longer a spy.
10505 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010506 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010507
10508 // It continues to receive the rest of the stylus gesture.
10509 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10510 overlay->consumeMotionMove();
10511 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10512 overlay->consumeMotionUp();
10513
10514 window->assertNoEvents();
10515}
10516
Prabir Pradhan5735a322022-04-11 17:23:34 +000010517struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010518 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010519 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010520 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10521 std::unique_ptr<InputDispatcher>& mDispatcher;
10522
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010523 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010524 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10525
10526 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010527 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010528 ADISPLAY_ID_DEFAULT, {100, 200},
10529 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10530 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10531 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10532 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10533 }
10534
10535 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010536 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010537 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010538 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010539 mPolicyFlags);
10540 }
10541
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010542 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010543 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10544 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010545 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10546 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010547 window->setOwnerInfo(mPid, mUid);
10548 return window;
10549 }
10550};
10551
10552using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10553
10554TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010555 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010556 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010557 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010558
10559 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10560 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10561 window->consumeMotionDown();
10562
10563 setFocusedWindow(window);
10564 window->consumeFocusEvent(true);
10565
10566 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10567 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10568 window->consumeKeyDown(ADISPLAY_ID_NONE);
10569}
10570
10571TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010572 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010573 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010574 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010575
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010576 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010577 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10578 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10579
10580 setFocusedWindow(window);
10581 window->consumeFocusEvent(true);
10582
10583 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10584 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10585 window->assertNoEvents();
10586}
10587
10588TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010589 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010590 auto window = owner.createWindow("Owned window");
10591 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010592 spy->setSpy(true);
10593 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010594 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010595
10596 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10597 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10598 spy->consumeMotionDown();
10599 window->consumeMotionDown();
10600}
10601
10602TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010603 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010604 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010605
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010606 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010607 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010608 randosSpy->setSpy(true);
10609 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010610 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010611
10612 // The event is targeted at owner's window, so injection should succeed, but the spy should
10613 // not receive the event.
10614 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10615 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10616 randosSpy->assertNoEvents();
10617 window->consumeMotionDown();
10618}
10619
10620TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010621 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010622 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010623
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010624 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010625 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010626 randosSpy->setSpy(true);
10627 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010628 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010629
10630 // A user that has injection permission can inject into any window.
10631 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010632 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010633 ADISPLAY_ID_DEFAULT));
10634 randosSpy->consumeMotionDown();
10635 window->consumeMotionDown();
10636
10637 setFocusedWindow(randosSpy);
10638 randosSpy->consumeFocusEvent(true);
10639
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010640 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010641 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10642 window->assertNoEvents();
10643}
10644
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010645TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010646 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010647 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010648
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010649 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010650 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010651 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10652 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010653 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010654
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010655 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010656 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10657 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10658 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010659 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010660}
10661
Garfield Tane84e6f92019-08-29 17:28:41 -070010662} // namespace android::inputdispatcher