blob: 2509c605737ac148f07784498cc1f863ffd63761 [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 Vishniakoub237f9e2023-07-21 16:42:23 -0700115/**
116 * If we expect to receive the event, the timeout can be made very long. When the test are running
117 * correctly, we will actually never wait until the end of the timeout because the wait will end
118 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
119 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
120 * developer can see the failure quickly (on human scale).
121 */
122static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
123/**
124 * When no event is expected, we can have a very short timeout. A large value here would slow down
125 * the tests. In the unlikely event of system being too slow, the event may still be present but the
126 * timeout would complete before it is consumed. This would result in test flakiness. If this
127 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
128 * would get noticed and addressed quickly.
129 */
130static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
131
Arthur Hungc539dbb2022-12-08 07:45:36 +0000132static constexpr int expectedWallpaperFlags =
133 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
134
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800135using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
136
Gang Wang342c9272020-01-13 13:15:04 -0500137/**
138 * Return a DOWN key event with KEYCODE_A.
139 */
140static KeyEvent getTestKeyEvent() {
141 KeyEvent event;
142
Garfield Tanfbe732e2020-01-24 11:26:14 -0800143 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
144 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
145 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500146 return event;
147}
148
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149// --- FakeInputDispatcherPolicy ---
150
151class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000152 struct AnrResult {
153 sp<IBinder> token{};
154 gui::Pid pid{gui::Pid::INVALID};
155 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000158 FakeInputDispatcherPolicy() = default;
159 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800160
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800161 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700162 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700163 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 EXPECT_EQ(event.getDisplayId(), args.displayId);
165
166 const auto& keyEvent = static_cast<const KeyEvent&>(event);
167 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
168 EXPECT_EQ(keyEvent.getAction(), args.action);
169 });
Jackal Guof9696682018-10-05 12:23:23 +0800170 }
171
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700172 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
173 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700174 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 EXPECT_EQ(event.getDisplayId(), args.displayId);
176
177 const auto& motionEvent = static_cast<const MotionEvent&>(event);
178 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
179 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000180 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
181 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
182 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700184 });
Jackal Guof9696682018-10-05 12:23:23 +0800185 }
186
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700187 void assertFilterInputEventWasNotCalled() {
188 std::scoped_lock lock(mLock);
189 ASSERT_EQ(nullptr, mFilteredEvent);
190 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800192 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700193 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 ASSERT_TRUE(mConfigurationChangedTime)
195 << "Timed out waiting for configuration changed call";
196 ASSERT_EQ(*mConfigurationChangedTime, when);
197 mConfigurationChangedTime = std::nullopt;
198 }
199
200 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700201 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800202 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800203 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800204 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
205 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
206 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
207 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
208 mLastNotifySwitch = std::nullopt;
209 }
210
chaviwfd6d3512019-03-25 13:23:49 -0700211 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700212 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800213 ASSERT_EQ(touchedToken, mOnPointerDownToken);
214 mOnPointerDownToken.clear();
215 }
216
217 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700218 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800219 ASSERT_TRUE(mOnPointerDownToken == nullptr)
220 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700221 }
222
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700223 // This function must be called soon after the expected ANR timer starts,
224 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500225 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700226 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800228 std::unique_lock lock(mLock);
229 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 ASSERT_NO_FATAL_FAILURE(
232 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700234 }
235
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000236 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800237 const sp<WindowInfoHandle>& window) {
238 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
239 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
240 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500241 }
242
Prabir Pradhanedd96402022-02-15 01:46:16 -0800243 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
244 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000245 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
248 AnrResult result;
249 ASSERT_NO_FATAL_FAILURE(result =
250 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000251 ASSERT_EQ(expectedToken, result.token);
252 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500253 }
254
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000256 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500257 std::unique_lock lock(mLock);
258 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800259 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
260 const auto& [token, _] = result;
261 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000262 }
263
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000265 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800266 std::unique_lock lock(mLock);
267 android::base::ScopedLockAssertion assumeLocked(mLock);
268 AnrResult result;
269 ASSERT_NO_FATAL_FAILURE(
270 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000271 ASSERT_EQ(expectedToken, result.token);
272 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 }
274
275 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000276 sp<IBinder> getResponsiveWindowToken() {
277 std::unique_lock lock(mLock);
278 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
280 const auto& [token, _] = result;
281 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700282 }
283
284 void assertNotifyAnrWasNotCalled() {
285 std::scoped_lock lock(mLock);
286 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_TRUE(mAnrWindows.empty());
288 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 << "ANR was not called, but please also consume the 'connection is responsive' "
290 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700291 }
292
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000293 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800294 std::unique_lock lock(mLock);
295 base::ScopedLockAssertion assumeLocked(mLock);
296
297 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
298 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000299 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800300 enabled;
301 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
303 << ") to be called.";
304 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800305 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000306 auto request = *mPointerCaptureRequest;
307 mPointerCaptureRequest.reset();
308 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800309 }
310
311 void assertSetPointerCaptureNotCalled() {
312 std::unique_lock lock(mLock);
313 base::ScopedLockAssertion assumeLocked(mLock);
314
315 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000316 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800317 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800321 }
322
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700323 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
324 const sp<IBinder>& targetToken) {
325 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800326 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800327 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800328 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800329 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800330 }
331
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800332 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
333 std::unique_lock lock(mLock);
334 base::ScopedLockAssertion assumeLocked(mLock);
335 std::optional<sp<IBinder>> receivedToken =
336 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
337 mNotifyInputChannelBroken);
338 ASSERT_TRUE(receivedToken.has_value());
339 ASSERT_EQ(token, *receivedToken);
340 }
341
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800342 /**
343 * Set policy timeout. A value of zero means next key will not be intercepted.
344 */
345 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
346 mInterceptKeyTimeout = timeout;
347 }
348
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700349 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
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
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700394 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
395
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000396 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000397
Prabir Pradhanedd96402022-02-15 01:46:16 -0800398 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
399 // for a specific container to become non-empty. When the container is non-empty, return the
400 // first entry from the container and erase it.
401 template <class T>
402 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
403 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
404 // If there is an ANR, Dispatcher won't be idle because there are still events
405 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
406 // before checking if ANR was called.
407 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
408 // to provide it some time to act. 100ms seems reasonable.
409 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
410 const std::chrono::time_point start = std::chrono::steady_clock::now();
411 std::optional<T> token =
412 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
413 if (!token.has_value()) {
414 ADD_FAILURE() << "Did not receive the ANR callback";
415 return {};
416 }
417
418 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
419 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
420 // the dispatcher started counting before this function was called
421 if (std::chrono::abs(timeout - waited) > 100ms) {
422 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
423 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
424 << "ms, but waited "
425 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
426 << "ms instead";
427 }
428 return *token;
429 }
430
431 template <class T>
432 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
433 std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock,
435 std::condition_variable& condition)
436 REQUIRES(mLock) {
437 condition.wait_for(lock, timeout,
438 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
439 if (storage.empty()) {
440 ADD_FAILURE() << "Did not receive the expected callback";
441 return std::nullopt;
442 }
443 T item = storage.front();
444 storage.pop();
445 return std::make_optional(item);
446 }
447
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600448 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700449 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800450 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800451 }
452
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000453 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700455 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800456 ASSERT_TRUE(pid.has_value());
457 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700458 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500459 }
460
Prabir Pradhanedd96402022-02-15 01:46:16 -0800461 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000462 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500463 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800464 ASSERT_TRUE(pid.has_value());
465 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500466 mNotifyAnr.notify_all();
467 }
468
469 void notifyNoFocusedWindowAnr(
470 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
471 std::scoped_lock lock(mLock);
472 mAnrApplications.push(applicationHandle);
473 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800474 }
475
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800476 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
477 std::scoped_lock lock(mLock);
478 mBrokenInputChannels.push(connectionToken);
479 mNotifyInputChannelBroken.notify_all();
480 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600482 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700483
Chris Yef59a2f42020-10-16 12:55:26 -0700484 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
485 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
486 const std::vector<float>& values) override {}
487
488 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
489 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000490
Chris Yefb552902021-02-03 17:18:37 -0800491 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
492
Prabir Pradhana41d2442023-04-20 21:30:40 +0000493 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700494 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000495 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700496 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000497 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
498 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800499 break;
500 }
501
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700502 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000503 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
504 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800505 break;
506 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700507 default: {
508 ADD_FAILURE() << "Should only filter keys or motions";
509 break;
510 }
Jackal Guof9696682018-10-05 12:23:23 +0800511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512 return true;
513 }
514
Prabir Pradhana41d2442023-04-20 21:30:40 +0000515 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
516 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800517 // Clear intercept state when we handled the event.
518 mInterceptKeyTimeout = 0ms;
519 }
520 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600522 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800523
Prabir Pradhana41d2442023-04-20 21:30:40 +0000524 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800525 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
526 // Clear intercept state so we could dispatch the event in next wake.
527 mInterceptKeyTimeout = 0ms;
528 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 }
530
Prabir Pradhana41d2442023-04-20 21:30:40 +0000531 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
532 uint32_t) override {
533 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534 }
535
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600536 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
537 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700538 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800539 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
540 * essentially a passthrough for notifySwitch.
541 */
Harry Cutts33476232023-01-30 19:57:29 +0000542 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 }
544
Josep del Riob3981622023-04-18 15:49:45 +0000545 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
546 std::scoped_lock lock(mLock);
547 mPokedUserActivity = true;
548 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700550 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
551 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
552 }
553
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600554 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700555 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700556 mOnPointerDownToken = newToken;
557 }
558
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000559 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800560 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000561 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800562 mPointerCaptureChangedCondition.notify_all();
563 }
564
arthurhungf452d0b2021-01-06 00:19:52 +0800565 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
566 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800567 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800568 mDropTargetWindowToken = token;
569 }
570
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000571 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000572 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000573 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
574 }
575
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700576 void assertFilterInputEventWasCalledInternal(
577 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800579 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700580 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800581 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700584} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586// --- InputDispatcherTest ---
587
588class InputDispatcherTest : public testing::Test {
589protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000590 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700591 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000593 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000594 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700595 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
596
Harry Cutts101ee9b2023-07-06 18:04:14 +0000597 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000598 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700599 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800600 }
601
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000602 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700603 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000604 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700605 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700607
608 /**
609 * Used for debugging when writing the test
610 */
611 void dumpDispatcherState() {
612 std::string dump;
613 mDispatcher->dump(dump);
614 std::stringstream ss(dump);
615 std::string to;
616
617 while (std::getline(ss, to, '\n')) {
618 ALOGE("%s", to.c_str());
619 }
620 }
Vishnu Nair958da932020-08-21 17:12:37 -0700621
Chavi Weingarten847e8512023-03-29 00:26:09 +0000622 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700623 FocusRequest request;
624 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000625 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700626 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
627 request.displayId = window->getInfo()->displayId;
628 mDispatcher->setFocusedWindow(request);
629 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630};
631
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
633 KeyEvent event;
634
635 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800636 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
637 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000638 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600639 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800640 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000641 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000642 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643 << "Should reject key events with undefined action.";
644
645 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800646 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
647 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600648 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800649 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000650 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000651 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 << "Should reject key events with ACTION_MULTIPLE.";
653}
654
655TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
656 MotionEvent event;
657 PointerProperties pointerProperties[MAX_POINTERS + 1];
658 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800659 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660 pointerProperties[i].clear();
661 pointerProperties[i].id = i;
662 pointerCoords[i].clear();
663 }
664
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800665 // Some constants commonly used below
666 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
667 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
668 constexpr int32_t metaState = AMETA_NONE;
669 constexpr MotionClassification classification = MotionClassification::NONE;
670
chaviw9eaa22c2020-07-01 16:21:27 -0700671 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800673 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000674 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700675 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700676 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
677 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000678 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800679 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000680 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000681 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800682 << "Should reject motion events with undefined action.";
683
684 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800685 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800686 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
687 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
688 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
689 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000690 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800691 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000692 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000693 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 << "Should reject motion events with pointer down index too large.";
695
Garfield Tanfbe732e2020-01-24 11:26:14 -0800696 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700697 AMOTION_EVENT_ACTION_POINTER_DOWN |
698 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700699 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
700 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700701 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000702 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800703 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000704 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000705 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 << "Should reject motion events with pointer down index too small.";
707
708 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800709 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800710 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
711 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
712 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
713 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000714 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800715 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000716 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000717 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718 << "Should reject motion events with pointer up index too large.";
719
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700721 AMOTION_EVENT_ACTION_POINTER_UP |
722 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700723 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
724 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700725 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000726 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800727 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000728 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000729 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800730 << "Should reject motion events with pointer up index too small.";
731
732 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800733 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
734 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700735 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700736 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
737 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000738 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000740 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000741 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800742 << "Should reject motion events with 0 pointers.";
743
Garfield Tanfbe732e2020-01-24 11:26:14 -0800744 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
745 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700746 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700747 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
748 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with more than MAX_POINTERS pointers.";
754
755 // Rejects motion events with invalid pointer ids.
756 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800757 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
758 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700759 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700760 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
761 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000762 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800763 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000764 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000765 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800766 << "Should reject motion events with pointer ids less than 0.";
767
768 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
770 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700771 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
773 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000774 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800775 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000776 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000777 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800778 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
779
780 // Rejects motion events with duplicate pointer ids.
781 pointerProperties[0].id = 1;
782 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800783 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
784 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700785 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700786 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
787 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000788 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800789 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000790 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000791 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800792 << "Should reject motion events with duplicate pointer ids.";
793}
794
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800795/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
796
797TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
798 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000799 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800800 ASSERT_TRUE(mDispatcher->waitForIdle());
801
802 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
803}
804
805TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000806 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
807 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000808 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800809
810 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
811 args.policyFlags |= POLICY_FLAG_TRUSTED;
812 mFakePolicy->assertNotifySwitchWasCalled(args);
813}
814
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700815namespace {
816
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700817static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700818// Default input dispatching timeout if there is no focused application or paused window
819// from which to determine an appropriate dispatching timeout.
820static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
821 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
822 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800823
824class FakeApplicationHandle : public InputApplicationHandle {
825public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700826 FakeApplicationHandle() {
827 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700828 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500829 mInfo.dispatchingTimeoutMillis =
830 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700831 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800832 virtual ~FakeApplicationHandle() {}
833
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000834 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700835
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500836 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
837 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700838 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800839};
840
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800841class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800842public:
Garfield Tan15601662020-09-22 15:32:38 -0700843 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800844 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700845 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800846 }
847
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700848 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700849 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700850 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700851 if (!consumeSeq) {
852 return nullptr;
853 }
854 finishEvent(*consumeSeq);
855 return event;
856 }
857
858 /**
859 * Receive an event without acknowledging it.
860 * Return the sequence number that could later be used to send finished signal.
861 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700862 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
863 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800864 uint32_t consumeSeq;
865 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800866
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 std::chrono::time_point start = std::chrono::steady_clock::now();
868 status_t status = WOULD_BLOCK;
869 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000870 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800871 &event);
872 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700873 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800874 break;
875 }
876 }
877
878 if (status == WOULD_BLOCK) {
879 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 }
882
883 if (status != OK) {
884 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 }
887 if (event == nullptr) {
888 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700889 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700891 if (outEvent != nullptr) {
892 *outEvent = event;
893 }
894 return consumeSeq;
895 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 /**
898 * To be used together with "receiveEvent" to complete the consumption of an event.
899 */
900 void finishEvent(uint32_t consumeSeq) {
901 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
902 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 }
904
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000905 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
906 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
907 ASSERT_EQ(OK, status);
908 }
909
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700910 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000911 std::optional<int32_t> expectedDisplayId,
912 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700913 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914
915 ASSERT_NE(nullptr, event) << mName.c_str()
916 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700918 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
919 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800920
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000921 if (expectedDisplayId.has_value()) {
922 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
923 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800924
Tiger Huang8664f8c2018-10-11 19:14:35 +0800925 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800927 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700928 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000929 if (expectedFlags.has_value()) {
930 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
931 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800932 break;
933 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800935 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700936 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedFlags.has_value()) {
938 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940 break;
941 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100943 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
944 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700945 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800946 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
947 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700948 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000949 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
950 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700951 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800952 FAIL() << "Use 'consumeDragEvent' for DRAG events";
953 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800954 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800955 }
956
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800957 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700958 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800959
960 if (event == nullptr) {
961 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
962 return nullptr;
963 }
964
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 if (event->getType() != InputEventType::MOTION) {
966 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800967 return nullptr;
968 }
969 return static_cast<MotionEvent*>(event);
970 }
971
972 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
973 MotionEvent* motionEvent = consumeMotion();
974 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
975 ASSERT_THAT(*motionEvent, matcher);
976 }
977
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100978 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700979 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100980 ASSERT_NE(nullptr, event) << mName.c_str()
981 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700982 ASSERT_EQ(InputEventType::FOCUS, event->getType())
983 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100984
985 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
986 << mName.c_str() << ": event displayId should always be NONE.";
987
988 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
989 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 }
991
Prabir Pradhan99987712020-11-10 18:43:05 -0800992 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700993 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800994 ASSERT_NE(nullptr, event) << mName.c_str()
995 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
997 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800998
999 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1000 << mName.c_str() << ": event displayId should always be NONE.";
1001
1002 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1003 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1004 }
1005
arthurhungb89ccb02020-12-30 16:19:01 +08001006 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001007 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001008 ASSERT_NE(nullptr, event) << mName.c_str()
1009 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001011
1012 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1013 << mName.c_str() << ": event displayId should always be NONE.";
1014
1015 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1016 EXPECT_EQ(isExiting, dragEvent.isExiting());
1017 EXPECT_EQ(x, dragEvent.getX());
1018 EXPECT_EQ(y, dragEvent.getY());
1019 }
1020
Antonio Kantekf16f2832021-09-28 04:39:20 +00001021 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001022 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001023 ASSERT_NE(nullptr, event) << mName.c_str()
1024 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001025 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1026 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001027
1028 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1031 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1032 }
1033
chaviwd1c23182019-12-20 18:44:56 -08001034 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001035 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001036 if (event == nullptr) {
1037 return;
1038 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001039 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001040 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1041 ADD_FAILURE() << "Received key event "
1042 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001044 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1045 ADD_FAILURE() << "Received motion event "
1046 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001047 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001048 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1049 ADD_FAILURE() << "Received focus event, hasFocus = "
1050 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001051 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001052 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1053 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1054 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001056 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1057 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1058 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 }
1060 FAIL() << mName.c_str()
1061 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001062 }
1063
1064 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1065
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001066 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1067
chaviwd1c23182019-12-20 18:44:56 -08001068protected:
1069 std::unique_ptr<InputConsumer> mConsumer;
1070 PreallocatedInputEventFactory mEventFactory;
1071
1072 std::string mName;
1073};
1074
chaviw3277faf2021-05-19 16:45:23 -05001075class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001076public:
1077 static const int32_t WIDTH = 600;
1078 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001079
Chris Yea209fde2020-07-22 13:54:51 -07001080 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001081 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001082 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001083 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001084 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001085 base::Result<std::unique_ptr<InputChannel>> channel =
1086 dispatcher->createInputChannel(name);
1087 token = (*channel)->getConnectionToken();
1088 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001089 }
1090
1091 inputApplicationHandle->updateInfo();
1092 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1093
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001094 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001095 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001096 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001097 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001098 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001099 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001100 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001101 mInfo.globalScaleFactor = 1.0;
1102 mInfo.touchableRegion.clear();
1103 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001104 mInfo.ownerPid = WINDOW_PID;
1105 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001106 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001107 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001108 }
1109
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001110 sp<FakeWindowHandle> clone(int32_t displayId) {
1111 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1112 handle->mInfo = mInfo;
1113 handle->mInfo.displayId = displayId;
1114 handle->mInfo.id = sId++;
1115 handle->mInputReceiver = mInputReceiver;
1116 return handle;
1117 }
1118
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001119 void setTouchable(bool touchable) {
1120 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1121 }
chaviwd1c23182019-12-20 18:44:56 -08001122
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001123 void setFocusable(bool focusable) {
1124 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1125 }
1126
1127 void setVisible(bool visible) {
1128 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1129 }
Vishnu Nair958da932020-08-21 17:12:37 -07001130
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001131 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001132 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001133 }
1134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setPaused(bool paused) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1137 }
1138
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001139 void setPreventSplitting(bool preventSplitting) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001141 }
1142
1143 void setSlippery(bool slippery) {
1144 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1145 }
1146
1147 void setWatchOutsideTouch(bool watchOutside) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1149 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001150
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001151 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1152
1153 void setInterceptsStylus(bool interceptsStylus) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1155 }
1156
1157 void setDropInput(bool dropInput) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1159 }
1160
1161 void setDropInputIfObscured(bool dropInputIfObscured) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1163 }
1164
1165 void setNoInputChannel(bool noInputChannel) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1167 }
1168
Josep del Riob3981622023-04-18 15:49:45 +00001169 void setDisableUserActivity(bool disableUserActivity) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1171 }
1172
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001173 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1174
chaviw3277faf2021-05-19 16:45:23 -05001175 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001176
Bernardo Rufino7393d172021-02-26 13:56:11 +00001177 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1178
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001179 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001180 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001181 mInfo.touchableRegion.clear();
1182 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001183
1184 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1185 ui::Transform translate;
1186 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1187 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001188 }
1189
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001190 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1191
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 void setIsWallpaper(bool isWallpaper) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1194 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001195
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 void setDupTouchToWallpaper(bool hasWallpaper) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1198 }
chaviwd1c23182019-12-20 18:44:56 -08001199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 void setTrustedOverlay(bool trustedOverlay) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1202 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001203
chaviw9eaa22c2020-07-01 16:21:27 -07001204 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1205 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1206 }
1207
1208 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001209
yunho.shinf4a80b82020-11-16 21:13:57 +09001210 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1211
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001212 KeyEvent* consumeKey() {
1213 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1214 if (event == nullptr) {
1215 ADD_FAILURE() << "Consume failed : no event";
1216 return nullptr;
1217 }
1218 if (event->getType() != InputEventType::KEY) {
1219 ADD_FAILURE() << "Instead of key event, got " << *event;
1220 return nullptr;
1221 }
1222 return static_cast<KeyEvent*>(event);
1223 }
1224
1225 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1226 KeyEvent* keyEvent = consumeKey();
1227 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1228 ASSERT_THAT(*keyEvent, matcher);
1229 }
1230
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001231 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001232 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001233 }
1234
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001235 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001236 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001237 }
1238
Svet Ganov5d3bc372020-01-26 23:11:07 -08001239 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001240 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001241 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1242 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001243 }
1244
1245 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001246 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001247 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1248 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001249 }
1250
1251 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001252 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001253 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1254 }
1255
1256 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1257 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001258 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001259 expectedFlags);
1260 }
1261
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001263 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1264 int32_t expectedFlags = 0) {
1265 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
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 consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
1272 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1273 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001274 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001275 }
1276
1277 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001278 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001280 expectedFlags);
1281 }
1282
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001283 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001285 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001286 expectedFlags);
1287 }
1288
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001289 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1290 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001291 MotionEvent* motionEvent = consumeMotion();
1292 ASSERT_NE(nullptr, motionEvent);
1293 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1294 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1295 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001296 }
1297
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001298 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1299 ASSERT_NE(mInputReceiver, nullptr)
1300 << "Cannot consume events from a window with no receiver";
1301 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1302 }
1303
Prabir Pradhan99987712020-11-10 18:43:05 -08001304 void consumeCaptureEvent(bool hasCapture) {
1305 ASSERT_NE(mInputReceiver, nullptr)
1306 << "Cannot consume events from a window with no receiver";
1307 mInputReceiver->consumeCaptureEvent(hasCapture);
1308 }
1309
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001310 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1311 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001312 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001313 ASSERT_THAT(*motionEvent, matcher);
1314 }
1315
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001316 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001317 std::optional<int32_t> expectedDisplayId,
1318 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001319 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1320 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1321 expectedFlags);
1322 }
1323
arthurhungb89ccb02020-12-30 16:19:01 +08001324 void consumeDragEvent(bool isExiting, float x, float y) {
1325 mInputReceiver->consumeDragEvent(isExiting, x, y);
1326 }
1327
Antonio Kantekf16f2832021-09-28 04:39:20 +00001328 void consumeTouchModeEvent(bool inTouchMode) {
1329 ASSERT_NE(mInputReceiver, nullptr)
1330 << "Cannot consume events from a window with no receiver";
1331 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1332 }
1333
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001334 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001335 if (mInputReceiver == nullptr) {
1336 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1337 return std::nullopt;
1338 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001339 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001340 }
1341
1342 void finishEvent(uint32_t sequenceNum) {
1343 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1344 mInputReceiver->finishEvent(sequenceNum);
1345 }
1346
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001347 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1348 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1349 mInputReceiver->sendTimeline(inputEventId, timeline);
1350 }
1351
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001352 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001353 if (mInputReceiver == nullptr) {
1354 return nullptr;
1355 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001356 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001357 }
1358
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001359 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001360 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001361 if (event == nullptr) {
1362 ADD_FAILURE() << "Consume failed : no event";
1363 return nullptr;
1364 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001365 if (event->getType() != InputEventType::MOTION) {
1366 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001367 return nullptr;
1368 }
1369 return static_cast<MotionEvent*>(event);
1370 }
1371
Arthur Hungb92218b2018-08-14 12:00:21 +08001372 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001373 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001374 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001375 return; // Can't receive events if the window does not have input channel
1376 }
1377 ASSERT_NE(nullptr, mInputReceiver)
1378 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001379 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001380 }
1381
chaviwaf87b3e2019-10-01 16:59:28 -07001382 sp<IBinder> getToken() { return mInfo.token; }
1383
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001384 const std::string& getName() { return mName; }
1385
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001386 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001387 mInfo.ownerPid = ownerPid;
1388 mInfo.ownerUid = ownerUid;
1389 }
1390
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001391 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001392
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001393 void destroyReceiver() { mInputReceiver = nullptr; }
1394
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001395 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1396
chaviwd1c23182019-12-20 18:44:56 -08001397private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001398 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001399 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001400 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001401 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001402 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001403};
1404
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001405std::atomic<int32_t> FakeWindowHandle::sId{1};
1406
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001407class FakeMonitorReceiver {
1408public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001409 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001410 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001411 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001412 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1413 }
1414
1415 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1416
1417 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1418 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1419 expectedFlags);
1420 }
1421
1422 std::optional<int32_t> receiveEvent() {
1423 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1424 }
1425
1426 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1427
1428 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1429 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1430 expectedDisplayId, expectedFlags);
1431 }
1432
1433 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1434 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1435 expectedDisplayId, expectedFlags);
1436 }
1437
1438 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1439 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1440 expectedDisplayId, expectedFlags);
1441 }
1442
1443 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1444 mInputReceiver->consumeMotionEvent(
1445 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1446 WithDisplayId(expectedDisplayId),
1447 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1448 }
1449
1450 void consumeMotionPointerDown(int32_t pointerIdx) {
1451 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1452 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1453 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1454 /*expectedFlags=*/0);
1455 }
1456
1457 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1458 mInputReceiver->consumeMotionEvent(matcher);
1459 }
1460
1461 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1462
1463 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1464
1465private:
1466 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1467};
1468
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001469static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001470 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 int32_t displayId = ADISPLAY_ID_NONE,
1472 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001473 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001474 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001475 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001476 KeyEvent event;
1477 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1478
1479 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001480 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001481 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1482 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001483
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001484 if (!allowKeyRepeat) {
1485 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1486 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001487 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001488 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001489}
1490
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001491static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1492 InputEventInjectionResult result =
1493 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1494 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1495 if (result != InputEventInjectionResult::TIMED_OUT) {
1496 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1497 }
1498}
1499
1500static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001502 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001503}
1504
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001505// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1506// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1507// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001508static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1509 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001510 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001511 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001512 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001513}
1514
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001515static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001516 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001517 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001518}
1519
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001521 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001522 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001524 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001525 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1526 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001527}
1528
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001529static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001530 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1531 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001532 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001533 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1534 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001535 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001536 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001537 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001538 MotionEventBuilder motionBuilder =
1539 MotionEventBuilder(action, source)
1540 .displayId(displayId)
1541 .eventTime(eventTime)
1542 .rawXCursorPosition(cursorPosition.x)
1543 .rawYCursorPosition(cursorPosition.y)
1544 .pointer(
1545 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1546 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1547 motionBuilder.downTime(eventTime);
1548 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001549
1550 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001551 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1552 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001553}
1554
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001555static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1556 int32_t displayId,
1557 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001558 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001559}
1560
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001561static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1562 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001563 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001564 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001565}
1566
Jackal Guof9696682018-10-05 12:23:23 +08001567static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1568 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1569 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001570 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001571 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1572 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001573
1574 return args;
1575}
1576
Josep del Riob3981622023-04-18 15:49:45 +00001577static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1578 int32_t displayId = ADISPLAY_ID_NONE) {
1579 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1580 // Define a valid key event.
1581 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001582 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001583 currentTime);
1584
1585 return args;
1586}
1587
1588static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1589 int32_t displayId = ADISPLAY_ID_NONE) {
1590 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1591 // Define a valid key event.
1592 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001593 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001594 AMETA_NONE, currentTime);
1595
1596 return args;
1597}
1598
Prabir Pradhan678438e2023-04-13 19:32:51 +00001599[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1600 int32_t displayId,
1601 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001602 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001603 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1604 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1605 }
1606
chaviwd1c23182019-12-20 18:44:56 -08001607 PointerProperties pointerProperties[pointerCount];
1608 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001609
chaviwd1c23182019-12-20 18:44:56 -08001610 for (size_t i = 0; i < pointerCount; i++) {
1611 pointerProperties[i].clear();
1612 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001613 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001614
chaviwd1c23182019-12-20 18:44:56 -08001615 pointerCoords[i].clear();
1616 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1617 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1618 }
Jackal Guof9696682018-10-05 12:23:23 +08001619
1620 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1621 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001622 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001623 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1624 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001625 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001626 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001627 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001628 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001629
1630 return args;
1631}
1632
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001633static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1634 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1635}
1636
chaviwd1c23182019-12-20 18:44:56 -08001637static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1638 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1639}
1640
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001641static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1642 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001643 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001644}
1645
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001646} // namespace
1647
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001648/**
1649 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1650 * broken channel.
1651 */
1652TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1654 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001655 sp<FakeWindowHandle>::make(application, mDispatcher,
1656 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001657
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001659
1660 // Window closes its channel, but the window remains.
1661 window->destroyReceiver();
1662 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1663}
1664
Arthur Hungb92218b2018-08-14 12:00:21 +08001665TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001667 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1668 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001672 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001674
1675 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001676 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001677}
1678
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001679TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1682 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001685 // Inject a MotionEvent to an unknown display.
1686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1689
1690 // Window should receive motion event.
1691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1692}
1693
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001695 * Calling onWindowInfosChanged once should not cause any issues.
1696 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697 * called twice.
1698 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001699TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001701 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1702 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001707 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710
1711 // Window should receive motion event.
1712 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1713}
1714
1715/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001716 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717 */
1718TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1721 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001724 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001728 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001730
1731 // Window should receive motion event.
1732 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1733}
1734
Arthur Hungb92218b2018-08-14 12:00:21 +08001735// The foreground window should receive the first touch down event.
1736TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001738 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001739 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001740 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001741 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001742
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 mDispatcher->onWindowInfosChanged(
1744 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001748
1749 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001750 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001751 windowSecond->assertNoEvents();
1752}
1753
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001754/**
1755 * Two windows: A top window, and a wallpaper behind the window.
1756 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1757 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001758 * 1. foregroundWindow <-- dup touch to wallpaper
1759 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001760 */
1761TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1763 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001764 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001765 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001766 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001767 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001768 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001770 mDispatcher->onWindowInfosChanged(
1771 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001773 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001774 {100, 200}))
1775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1776
1777 // Both foreground window and its wallpaper should receive the touch down
1778 foregroundWindow->consumeMotionDown();
1779 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1780
1781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001782 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001783 ADISPLAY_ID_DEFAULT, {110, 200}))
1784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1785
1786 foregroundWindow->consumeMotionMove();
1787 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1788
1789 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001790 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001791 foregroundWindow->consumeMotionCancel();
1792 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1793 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1794}
1795
1796/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001797 * Two fingers down on the window, and lift off the first finger.
1798 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1799 * contains a single pointer.
1800 */
1801TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1803 sp<FakeWindowHandle> window =
1804 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1805
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001806 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001807 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1809 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1810 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001811 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001812 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1813 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1814 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1815 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001816 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001817 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1818 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1819 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1820 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001821 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1822 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1823 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1824
1825 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001826 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001827 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1828 window->consumeMotionEvent(
1829 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1830}
1831
1832/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001833 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1834 * with the following differences:
1835 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1836 * clean up the connection.
1837 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1838 * Ensure that there's no crash in the dispatcher.
1839 */
1840TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1842 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001843 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001844 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001845 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001846 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001847 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001848
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001849 mDispatcher->onWindowInfosChanged(
1850 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 {100, 200}))
1854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1855
1856 // Both foreground window and its wallpaper should receive the touch down
1857 foregroundWindow->consumeMotionDown();
1858 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1859
1860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862 ADISPLAY_ID_DEFAULT, {110, 200}))
1863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1864
1865 foregroundWindow->consumeMotionMove();
1866 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1867
1868 // Wallpaper closes its channel, but the window remains.
1869 wallpaperWindow->destroyReceiver();
1870 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1871
1872 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1873 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001874 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001875 foregroundWindow->consumeMotionCancel();
1876}
1877
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878class ShouldSplitTouchFixture : public InputDispatcherTest,
1879 public ::testing::WithParamInterface<bool> {};
1880INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1881 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001882/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 * A single window that receives touch (on top), and a wallpaper window underneath it.
1884 * The top window gets a multitouch gesture.
1885 * Ensure that wallpaper gets the same gesture.
1886 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001889 sp<FakeWindowHandle> foregroundWindow =
1890 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1891 foregroundWindow->setDupTouchToWallpaper(true);
1892 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893
1894 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001895 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001896 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001898 mDispatcher->onWindowInfosChanged(
1899 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900
1901 // Touch down on top window
1902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 {100, 100}))
1905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1906
1907 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001908 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1910
1911 // Second finger down on the top window
1912 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001913 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1916 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917 .build();
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001919 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920 InputEventInjectionSync::WAIT_FOR_RESULT))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922
Harry Cutts33476232023-01-30 19:57:29 +00001923 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1924 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926
1927 const MotionEvent secondFingerUpEvent =
1928 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1929 .displayId(ADISPLAY_ID_DEFAULT)
1930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001933 .build();
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001936 InputEventInjectionSync::WAIT_FOR_RESULT))
1937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1938 foregroundWindow->consumeMotionPointerUp(0);
1939 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1940
1941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001942 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001943 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1944 AINPUT_SOURCE_TOUCHSCREEN)
1945 .displayId(ADISPLAY_ID_DEFAULT)
1946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001947 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001948 .x(100)
1949 .y(100))
1950 .build(),
1951 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1953 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1954 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955}
1956
1957/**
1958 * Two windows: a window on the left and window on the right.
1959 * A third window, wallpaper, is behind both windows, and spans both top windows.
1960 * The first touch down goes to the left window. A second pointer touches down on the right window.
1961 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1962 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1963 * ACTION_POINTER_DOWN(1).
1964 */
1965TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1967 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001968 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001970 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971
1972 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001973 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001975 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976
1977 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001978 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001980 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001982 mDispatcher->onWindowInfosChanged(
1983 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1984 {},
1985 0,
1986 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987
1988 // Touch down on left window
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 {100, 100}))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 // Both foreground window and its wallpaper should receive the touch down
1995 leftWindow->consumeMotionDown();
1996 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1997
1998 // Second finger down on the right window
1999 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002000 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002001 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002002 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2003 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 .build();
2005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002006 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 InputEventInjectionSync::WAIT_FOR_RESULT))
2008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2009
2010 leftWindow->consumeMotionMove();
2011 // Since the touch is split, right window gets ACTION_DOWN
2012 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002013 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014 expectedWallpaperFlags);
2015
2016 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002017 mDispatcher->onWindowInfosChanged(
2018 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002019 leftWindow->consumeMotionCancel();
2020 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2021 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2022
2023 // The pointer that's still down on the right window moves, and goes to the right window only.
2024 // As far as the dispatcher's concerned though, both pointers are still present.
2025 const MotionEvent secondFingerMoveEvent =
2026 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2027 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002028 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2029 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 .build();
2031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002032 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 InputEventInjectionSync::WAIT_FOR_RESULT));
2034 rightWindow->consumeMotionMove();
2035
2036 leftWindow->assertNoEvents();
2037 rightWindow->assertNoEvents();
2038 wallpaperWindow->assertNoEvents();
2039}
2040
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041/**
2042 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2043 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2044 * The right window should receive ACTION_DOWN.
2045 */
2046TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 sp<FakeWindowHandle> leftWindow =
2049 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2050 leftWindow->setFrame(Rect(0, 0, 200, 200));
2051 leftWindow->setDupTouchToWallpaper(true);
2052 leftWindow->setSlippery(true);
2053
2054 sp<FakeWindowHandle> rightWindow =
2055 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2056 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002057
2058 sp<FakeWindowHandle> wallpaperWindow =
2059 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2060 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002061
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002062 mDispatcher->onWindowInfosChanged(
2063 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2064 {},
2065 0,
2066 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002067
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002070 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002073
2074 // Both foreground window and its wallpaper should receive the touch down
2075 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002076 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2077
Arthur Hungc539dbb2022-12-08 07:45:36 +00002078 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002080 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2083
Arthur Hungc539dbb2022-12-08 07:45:36 +00002084 leftWindow->consumeMotionCancel();
2085 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2086 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002087}
2088
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002089/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002090 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2091 * interactive, it might stop sending this flag.
2092 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2093 * to have a consistent input stream.
2094 *
2095 * Test procedure:
2096 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2097 * DOWN (new gesture).
2098 *
2099 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2100 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2101 *
2102 * We technically just need a single window here, but we are using two windows (spy on top and a
2103 * regular window below) to emulate the actual situation where it happens on the device.
2104 */
2105TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2107 sp<FakeWindowHandle> spyWindow =
2108 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2109 spyWindow->setFrame(Rect(0, 0, 200, 200));
2110 spyWindow->setTrustedOverlay(true);
2111 spyWindow->setSpy(true);
2112
2113 sp<FakeWindowHandle> window =
2114 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2115 window->setFrame(Rect(0, 0, 200, 200));
2116
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002117 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002119
2120 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002121 mDispatcher->notifyMotion(
2122 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2123 .deviceId(touchDeviceId)
2124 .policyFlags(DEFAULT_POLICY_FLAGS)
2125 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2126 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127
Prabir Pradhan678438e2023-04-13 19:32:51 +00002128 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2129 .deviceId(touchDeviceId)
2130 .policyFlags(DEFAULT_POLICY_FLAGS)
2131 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2132 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2133 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2135 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2136 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2137 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2138
2139 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002140 mDispatcher->notifyMotion(
2141 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2142 .deviceId(touchDeviceId)
2143 .policyFlags(0)
2144 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2145 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2146 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002147 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2148 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2149
2150 // We don't need to reset the device to reproduce the issue, but the reset event typically
2151 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002152 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002153
2154 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002155 mDispatcher->notifyMotion(
2156 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2157 .deviceId(touchDeviceId)
2158 .policyFlags(DEFAULT_POLICY_FLAGS)
2159 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2160 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2162 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2163
2164 // No more events
2165 spyWindow->assertNoEvents();
2166 window->assertNoEvents();
2167}
2168
2169/**
Linnan Li907ae732023-09-05 17:14:21 +08002170 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2171 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2172 * interactive, it might stop sending this flag.
2173 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2174 * the consistency of the hover event in this case.
2175 *
2176 * Test procedure:
2177 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2178 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2179 *
2180 * We expect to receive two full streams of hover events.
2181 */
2182TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2184
2185 sp<FakeWindowHandle> window =
2186 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2187 window->setFrame(Rect(0, 0, 300, 300));
2188
2189 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2190
2191 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2192 .policyFlags(DEFAULT_POLICY_FLAGS)
2193 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2194 .build());
2195 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2196
2197 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2198 .policyFlags(DEFAULT_POLICY_FLAGS)
2199 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2200 .build());
2201 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2202
2203 // Send hover exit without the default policy flags.
2204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2205 .policyFlags(0)
2206 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2207 .build());
2208
2209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2210
2211 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2212 // right event.
2213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2214 .policyFlags(DEFAULT_POLICY_FLAGS)
2215 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2216 .build());
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2218
2219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2220 .policyFlags(DEFAULT_POLICY_FLAGS)
2221 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2222 .build());
2223 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2224
2225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2226 .policyFlags(DEFAULT_POLICY_FLAGS)
2227 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2228 .build());
2229 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2230}
2231
2232/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002233 * Two windows: a window on the left and a window on the right.
2234 * Mouse is hovered from the right window into the left window.
2235 * Next, we tap on the left window, where the cursor was last seen.
2236 * The second tap is done onto the right window.
2237 * The mouse and tap are from two different devices.
2238 * We technically don't need to set the downtime / eventtime for these events, but setting these
2239 * explicitly helps during debugging.
2240 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2241 * In the buggy implementation, a tap on the right window would cause a crash.
2242 */
2243TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2245 sp<FakeWindowHandle> leftWindow =
2246 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2247 leftWindow->setFrame(Rect(0, 0, 200, 200));
2248
2249 sp<FakeWindowHandle> rightWindow =
2250 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2251 rightWindow->setFrame(Rect(200, 0, 400, 200));
2252
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002253 mDispatcher->onWindowInfosChanged(
2254 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002255 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2256 // stale.
2257 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2258 const int32_t mouseDeviceId = 6;
2259 const int32_t touchDeviceId = 4;
2260 // Move the cursor from right
2261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002262 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002263 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2264 AINPUT_SOURCE_MOUSE)
2265 .deviceId(mouseDeviceId)
2266 .downTime(baseTime + 10)
2267 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002268 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002269 .build()));
2270 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2271
2272 // .. to the left window
2273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002274 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002275 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2276 AINPUT_SOURCE_MOUSE)
2277 .deviceId(mouseDeviceId)
2278 .downTime(baseTime + 10)
2279 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002280 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002281 .build()));
2282 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2283 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2284 // Now tap the left window
2285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002286 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002287 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2288 AINPUT_SOURCE_TOUCHSCREEN)
2289 .deviceId(touchDeviceId)
2290 .downTime(baseTime + 40)
2291 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002292 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002293 .build()));
2294 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2295 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2296
2297 // release tap
2298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002299 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002300 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2301 AINPUT_SOURCE_TOUCHSCREEN)
2302 .deviceId(touchDeviceId)
2303 .downTime(baseTime + 40)
2304 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002305 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002306 .build()));
2307 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2308
2309 // Tap the window on the right
2310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002311 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002312 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2313 AINPUT_SOURCE_TOUCHSCREEN)
2314 .deviceId(touchDeviceId)
2315 .downTime(baseTime + 60)
2316 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002317 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002318 .build()));
2319 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2320
2321 // release tap
2322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002323 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002324 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2325 AINPUT_SOURCE_TOUCHSCREEN)
2326 .deviceId(touchDeviceId)
2327 .downTime(baseTime + 60)
2328 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002329 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002330 .build()));
2331 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2332
2333 // No more events
2334 leftWindow->assertNoEvents();
2335 rightWindow->assertNoEvents();
2336}
2337
2338/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002339 * Start hovering in a window. While this hover is still active, make another window appear on top.
2340 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2341 * While the top window is present, the hovering is stopped.
2342 * Later, hovering gets resumed again.
2343 * Ensure that new hover gesture is handled correctly.
2344 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2345 * to the window that's currently being hovered over.
2346 */
2347TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2349 sp<FakeWindowHandle> window =
2350 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2351 window->setFrame(Rect(0, 0, 200, 200));
2352
2353 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002354 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002355
2356 // Start hovering in the window
2357 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2358 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2359 .build());
2360 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2361
2362 // Now, an obscuring window appears!
2363 sp<FakeWindowHandle> obscuringWindow =
2364 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2365 ADISPLAY_ID_DEFAULT,
2366 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2367 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2368 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2369 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2370 obscuringWindow->setNoInputChannel(true);
2371 obscuringWindow->setFocusable(false);
2372 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002373 mDispatcher->onWindowInfosChanged(
2374 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002375
2376 // While this new obscuring window is present, the hovering is stopped
2377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2378 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2379 .build());
2380 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2381
2382 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002383 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002384
2385 // And a new hover gesture starts.
2386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2388 .build());
2389 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2390}
2391
2392/**
2393 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2394 * the obscuring window.
2395 */
2396TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2398 sp<FakeWindowHandle> window =
2399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2400 window->setFrame(Rect(0, 0, 200, 200));
2401
2402 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002403 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002404
2405 // Start hovering in the window
2406 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2407 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2408 .build());
2409 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2410
2411 // Now, an obscuring window appears!
2412 sp<FakeWindowHandle> obscuringWindow =
2413 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2414 ADISPLAY_ID_DEFAULT,
2415 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2416 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2417 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2418 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2419 obscuringWindow->setNoInputChannel(true);
2420 obscuringWindow->setFocusable(false);
2421 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002422 mDispatcher->onWindowInfosChanged(
2423 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002424
2425 // While this new obscuring window is present, the hovering continues. The event can't go to the
2426 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2428 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2429 .build());
2430 obscuringWindow->assertNoEvents();
2431 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2432
2433 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002434 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002435
2436 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2437 // so it should generate a HOVER_ENTER
2438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2439 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2440 .build());
2441 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2442
2443 // Now the MOVE should be getting dispatched normally
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2445 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2446 .build());
2447 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2448}
2449
2450/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002451 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2452 * events are delivered to the window.
2453 */
2454TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2456 sp<FakeWindowHandle> window =
2457 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2458 window->setFrame(Rect(0, 0, 200, 200));
2459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2460
2461 // Start hovering in the window
2462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2463 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2464 .build());
2465 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2466
2467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2468 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2469 .build());
2470 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2471
2472 // Scroll with the mouse
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2474 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2475 .build());
2476 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2477}
2478
2479using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2480
2481/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002482 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2483 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002484 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002485TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2487 sp<FakeWindowHandle> window =
2488 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2489 window->setFrame(Rect(0, 0, 200, 200));
2490
2491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2492
2493 constexpr int32_t touchDeviceId = 4;
2494 constexpr int32_t stylusDeviceId = 2;
2495
2496 // Stylus down
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2498 .deviceId(stylusDeviceId)
2499 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2500 .build());
2501 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2502
2503 // Touch down
2504 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2505 .deviceId(touchDeviceId)
2506 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2507 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002508
2509 // Touch move
2510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2511 .deviceId(touchDeviceId)
2512 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2513 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002514 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002515
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002516 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2518 .deviceId(stylusDeviceId)
2519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2520 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002521 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2522 WithCoords(101, 111)));
2523
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524 window->assertNoEvents();
2525}
2526
2527/**
2528 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002529 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002530 * Similar test as above, but with added SPY window.
2531 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002532TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2534 sp<FakeWindowHandle> window =
2535 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2536 sp<FakeWindowHandle> spyWindow =
2537 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2538 spyWindow->setFrame(Rect(0, 0, 200, 200));
2539 spyWindow->setTrustedOverlay(true);
2540 spyWindow->setSpy(true);
2541 window->setFrame(Rect(0, 0, 200, 200));
2542
2543 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2544
2545 constexpr int32_t touchDeviceId = 4;
2546 constexpr int32_t stylusDeviceId = 2;
2547
2548 // Stylus down
2549 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2550 .deviceId(stylusDeviceId)
2551 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2552 .build());
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2554 spyWindow->consumeMotionEvent(
2555 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2556
2557 // Touch down
2558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2559 .deviceId(touchDeviceId)
2560 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2561 .build());
2562
2563 // Touch move
2564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2565 .deviceId(touchDeviceId)
2566 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2567 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002568
2569 // Touch is ignored because stylus is already down
2570
2571 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2573 .deviceId(stylusDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2575 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002576 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2577 WithCoords(101, 111)));
2578 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2579 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002580
2581 window->assertNoEvents();
2582 spyWindow->assertNoEvents();
2583}
2584
2585/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002586 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2587 * touch is not dropped, because stylus hover should be ignored.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002589TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2591 sp<FakeWindowHandle> window =
2592 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2593 window->setFrame(Rect(0, 0, 200, 200));
2594
2595 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2596
2597 constexpr int32_t touchDeviceId = 4;
2598 constexpr int32_t stylusDeviceId = 2;
2599
2600 // Stylus down on the window
2601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2602 .deviceId(stylusDeviceId)
2603 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2604 .build());
2605 window->consumeMotionEvent(
2606 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2607
2608 // Touch down on window
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2612 .build());
2613 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2614 .deviceId(touchDeviceId)
2615 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2616 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002617
2618 // Stylus hover is canceled because touch is down
2619 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT),
2620 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2621 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2622 WithCoords(140, 145)));
2623 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2624 WithCoords(141, 146)));
2625
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002626 // Subsequent stylus movements are ignored
2627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2628 .deviceId(stylusDeviceId)
2629 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2630 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002631
2632 // but subsequent touches continue to be delivered
2633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2636 .build());
2637 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2638 WithCoords(142, 147)));
2639}
2640
2641/**
2642 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2643 * Ensure that touch is not canceled, because stylus hover should be dropped.
2644 */
2645TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2647 sp<FakeWindowHandle> window =
2648 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2649 window->setFrame(Rect(0, 0, 200, 200));
2650
2651 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2652
2653 constexpr int32_t touchDeviceId = 4;
2654 constexpr int32_t stylusDeviceId = 2;
2655
2656 // Touch down on window
2657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2658 .deviceId(touchDeviceId)
2659 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2660 .build());
2661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2662 .deviceId(touchDeviceId)
2663 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2664 .build());
2665 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2666 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2667
2668 // Stylus hover on the window
2669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2670 .deviceId(stylusDeviceId)
2671 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2672 .build());
2673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2674 .deviceId(stylusDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2676 .build());
2677 // Stylus hover movement is dropped
2678
2679 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
2681 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2682 .build());
2683 // Subsequent touch movements are delivered correctly
2684 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2685 WithCoords(142, 147)));
2686}
2687
2688/**
2689 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2690 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2691 * become active.
2692 */
2693TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2695 sp<FakeWindowHandle> window =
2696 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2697 window->setFrame(Rect(0, 0, 200, 200));
2698
2699 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2700
2701 constexpr int32_t stylusDeviceId1 = 3;
2702 constexpr int32_t stylusDeviceId2 = 5;
2703
2704 // Touch down on window
2705 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2706 .deviceId(stylusDeviceId1)
2707 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2708 .build());
2709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2710 .deviceId(stylusDeviceId1)
2711 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2712 .build());
2713 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2714 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2715
2716 // Second stylus down
2717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2718 .deviceId(stylusDeviceId2)
2719 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2720 .build());
2721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2722 .deviceId(stylusDeviceId2)
2723 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2724 .build());
2725
2726 // First stylus is canceled, second one takes over.
2727 window->consumeMotionEvent(
2728 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2729 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2730 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2731
2732 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2733 .deviceId(stylusDeviceId1)
2734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2735 .build());
2736 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002737 window->assertNoEvents();
2738}
2739
2740/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002741 * One window. Touch down on the window. Then, stylus down on the window from another device.
2742 * Ensure that is canceled, because stylus down should be preferred over touch.
2743 */
2744TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2746 sp<FakeWindowHandle> window =
2747 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2748 window->setFrame(Rect(0, 0, 200, 200));
2749
2750 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2751
2752 constexpr int32_t touchDeviceId = 4;
2753 constexpr int32_t stylusDeviceId = 2;
2754
2755 // Touch down on window
2756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2757 .deviceId(touchDeviceId)
2758 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2759 .build());
2760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2761 .deviceId(touchDeviceId)
2762 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2763 .build());
2764 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2765 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2766
2767 // Stylus down on the window
2768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2769 .deviceId(stylusDeviceId)
2770 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2771 .build());
2772 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2773 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2774
2775 // Subsequent stylus movements are delivered correctly
2776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2777 .deviceId(stylusDeviceId)
2778 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2779 .build());
2780 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2781 WithCoords(101, 111)));
2782}
2783
2784/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002785 * Two windows: a window on the left and a window on the right.
2786 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2787 * down. Then, on the left window, also place second touch pointer down.
2788 * This test tries to reproduce a crash.
2789 * In the buggy implementation, second pointer down on the left window would cause a crash.
2790 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002791TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2793 sp<FakeWindowHandle> leftWindow =
2794 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2795 leftWindow->setFrame(Rect(0, 0, 200, 200));
2796
2797 sp<FakeWindowHandle> rightWindow =
2798 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2799 rightWindow->setFrame(Rect(200, 0, 400, 200));
2800
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002801 mDispatcher->onWindowInfosChanged(
2802 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002803
2804 const int32_t touchDeviceId = 4;
2805 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002806
2807 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2809 .deviceId(mouseDeviceId)
2810 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2811 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812 leftWindow->consumeMotionEvent(
2813 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2814
2815 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2817 .deviceId(mouseDeviceId)
2818 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821
2822 leftWindow->consumeMotionEvent(
2823 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2824 leftWindow->consumeMotionEvent(
2825 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2826
Prabir Pradhan678438e2023-04-13 19:32:51 +00002827 mDispatcher->notifyMotion(
2828 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2829 .deviceId(mouseDeviceId)
2830 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2831 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2832 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2833 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002834 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2835
2836 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2838 .deviceId(touchDeviceId)
2839 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2840 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002841 leftWindow->assertNoEvents();
2842
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2844
2845 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002846 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2847 .deviceId(touchDeviceId)
2848 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2849 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2850 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002851 // Since this is now a new splittable pointer going down on the left window, and it's coming
2852 // from a different device, the current gesture in the left window (pointer down) should first
2853 // be canceled.
2854 leftWindow->consumeMotionEvent(
2855 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002856 leftWindow->consumeMotionEvent(
2857 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2858 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2859 // current implementation.
2860 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2861 rightWindow->consumeMotionEvent(
2862 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2863
2864 leftWindow->assertNoEvents();
2865 rightWindow->assertNoEvents();
2866}
2867
2868/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002869 * Two windows: a window on the left and a window on the right.
2870 * Mouse is hovered on the left window and stylus is hovered on the right window.
2871 */
2872TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2874 sp<FakeWindowHandle> leftWindow =
2875 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2876 leftWindow->setFrame(Rect(0, 0, 200, 200));
2877
2878 sp<FakeWindowHandle> rightWindow =
2879 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2880 rightWindow->setFrame(Rect(200, 0, 400, 200));
2881
2882 mDispatcher->onWindowInfosChanged(
2883 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2884
2885 const int32_t stylusDeviceId = 3;
2886 const int32_t mouseDeviceId = 6;
2887
2888 // Start hovering over the left window
2889 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2890 .deviceId(mouseDeviceId)
2891 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2892 .build());
2893 leftWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2895
2896 // Stylus hovered on right window
2897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2898 .deviceId(stylusDeviceId)
2899 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2900 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002901 rightWindow->consumeMotionEvent(
2902 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2903
2904 // Subsequent HOVER_MOVE events are dispatched correctly.
2905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2906 .deviceId(mouseDeviceId)
2907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2908 .build());
2909 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002910 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002911
2912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2913 .deviceId(stylusDeviceId)
2914 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2915 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002916 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002917 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002918
2919 leftWindow->assertNoEvents();
2920 rightWindow->assertNoEvents();
2921}
2922
2923/**
2924 * Three windows: a window on the left and a window on the right.
2925 * And a spy window that's positioned above all of them.
2926 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2927 * Check the stream that's received by the spy.
2928 */
2929TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2931
2932 sp<FakeWindowHandle> spyWindow =
2933 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2934 spyWindow->setFrame(Rect(0, 0, 400, 400));
2935 spyWindow->setTrustedOverlay(true);
2936 spyWindow->setSpy(true);
2937
2938 sp<FakeWindowHandle> leftWindow =
2939 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2940 leftWindow->setFrame(Rect(0, 0, 200, 200));
2941
2942 sp<FakeWindowHandle> rightWindow =
2943 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2944
2945 rightWindow->setFrame(Rect(200, 0, 400, 200));
2946
2947 mDispatcher->onWindowInfosChanged(
2948 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2949
2950 const int32_t stylusDeviceId = 1;
2951 const int32_t touchDeviceId = 2;
2952
2953 // Stylus down on the left window
2954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2955 .deviceId(stylusDeviceId)
2956 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2957 .build());
2958 leftWindow->consumeMotionEvent(
2959 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2960 spyWindow->consumeMotionEvent(
2961 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2962
2963 // Touch down on the right window
2964 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2965 .deviceId(touchDeviceId)
2966 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2967 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002968 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002969 rightWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002971
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002972 // Spy window does not receive touch events, because stylus events take precedence, and it
2973 // already has an active stylus gesture.
2974
2975 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2977 .deviceId(stylusDeviceId)
2978 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2979 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002980 leftWindow->consumeMotionEvent(
2981 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2982 spyWindow->consumeMotionEvent(
2983 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002984
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002985 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2987 .deviceId(touchDeviceId)
2988 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2989 .build());
2990 rightWindow->consumeMotionEvent(
2991 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002992
2993 spyWindow->assertNoEvents();
2994 leftWindow->assertNoEvents();
2995 rightWindow->assertNoEvents();
2996}
2997
2998/**
2999 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3000 * both.
3001 * Check hover in left window and touch down in the right window.
3002 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003003 * At the same time, left and right should be getting independent streams of hovering and touch,
3004 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003005 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003006TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlockedByTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3008
3009 sp<FakeWindowHandle> spyWindow =
3010 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3011 spyWindow->setFrame(Rect(0, 0, 400, 400));
3012 spyWindow->setTrustedOverlay(true);
3013 spyWindow->setSpy(true);
3014
3015 sp<FakeWindowHandle> leftWindow =
3016 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3017 leftWindow->setFrame(Rect(0, 0, 200, 200));
3018
3019 sp<FakeWindowHandle> rightWindow =
3020 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3021 rightWindow->setFrame(Rect(200, 0, 400, 200));
3022
3023 mDispatcher->onWindowInfosChanged(
3024 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3025
3026 const int32_t stylusDeviceId = 1;
3027 const int32_t touchDeviceId = 2;
3028
3029 // Stylus hover on the left window
3030 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3031 .deviceId(stylusDeviceId)
3032 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3033 .build());
3034 leftWindow->consumeMotionEvent(
3035 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3036 spyWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3038
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003039 // Touch down on the right window. Spy doesn't receive this touch because it already has
3040 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003041 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3042 .deviceId(touchDeviceId)
3043 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3044 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003045 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003046 spyWindow->consumeMotionEvent(
3047 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3048 spyWindow->consumeMotionEvent(
3049 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3050 rightWindow->consumeMotionEvent(
3051 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3052
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003053 // Stylus movements continue. They should be delivered to the left window only.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3055 .deviceId(stylusDeviceId)
3056 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3057 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003058 leftWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003060
3061 // Touch movements continue. They should be delivered to the right window and to the spy
3062 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3063 .deviceId(touchDeviceId)
3064 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3065 .build());
3066 spyWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3068 rightWindow->consumeMotionEvent(
3069 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3070
3071 spyWindow->assertNoEvents();
3072 leftWindow->assertNoEvents();
3073 rightWindow->assertNoEvents();
3074}
3075
3076/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003077 * On a single window, use two different devices: mouse and touch.
3078 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3079 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3080 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3081 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3082 * represent a new gesture.
3083 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003084TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3086 sp<FakeWindowHandle> window =
3087 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3088 window->setFrame(Rect(0, 0, 400, 400));
3089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091
3092 const int32_t touchDeviceId = 4;
3093 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003094
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003095 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3097 .deviceId(touchDeviceId)
3098 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3099 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3104 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3113 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3114 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3115
3116 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3118 .deviceId(mouseDeviceId)
3119 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3121 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122
3123 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003124 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3126
Prabir Pradhan678438e2023-04-13 19:32:51 +00003127 mDispatcher->notifyMotion(
3128 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3129 .deviceId(mouseDeviceId)
3130 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3131 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3132 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3133 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3135
3136 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003137 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3138 .deviceId(touchDeviceId)
3139 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3140 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3141 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003142 // Since we already canceled this touch gesture, it will be ignored until a completely new
3143 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3144 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3145 // However, mouse movements should continue to work.
3146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3147 .deviceId(mouseDeviceId)
3148 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3150 .build());
3151 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3152
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003153 window->assertNoEvents();
3154}
3155
3156/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003157 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3158 * the injected event.
3159 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003160TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3162 sp<FakeWindowHandle> window =
3163 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3164 window->setFrame(Rect(0, 0, 400, 400));
3165
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003166 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003167
3168 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003169 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3170 // completion.
3171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003172 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3174 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003175 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003176 .build()));
3177 window->consumeMotionEvent(
3178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3179
3180 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3181 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3183 .deviceId(touchDeviceId)
3184 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3185 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003186
3187 window->consumeMotionEvent(
3188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3189 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3190}
3191
3192/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003193 * This test is similar to the test above, but the sequence of injected events is different.
3194 *
3195 * Two windows: a window on the left and a window on the right.
3196 * Mouse is hovered over the left window.
3197 * Next, we tap on the left window, where the cursor was last seen.
3198 *
3199 * After that, we inject one finger down onto the right window, and then a second finger down onto
3200 * the left window.
3201 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3202 * window (first), and then another on the left window (second).
3203 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3204 * In the buggy implementation, second finger down on the left window would cause a crash.
3205 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003206TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3208 sp<FakeWindowHandle> leftWindow =
3209 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3210 leftWindow->setFrame(Rect(0, 0, 200, 200));
3211
3212 sp<FakeWindowHandle> rightWindow =
3213 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3214 rightWindow->setFrame(Rect(200, 0, 400, 200));
3215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003216 mDispatcher->onWindowInfosChanged(
3217 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003218
3219 const int32_t mouseDeviceId = 6;
3220 const int32_t touchDeviceId = 4;
3221 // Hover over the left window. Keep the cursor there.
3222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003223 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3225 AINPUT_SOURCE_MOUSE)
3226 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003228 .build()));
3229 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3230
3231 // Tap on left window
3232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003234 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3235 AINPUT_SOURCE_TOUCHSCREEN)
3236 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003237 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003238 .build()));
3239
3240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003241 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003242 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3243 AINPUT_SOURCE_TOUCHSCREEN)
3244 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003246 .build()));
3247 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3248 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3249 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3250
3251 // First finger down on right window
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003254 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3255 AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 .build()));
3259 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3260
3261 // Second finger down on the left window
3262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003263 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003264 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003266 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3267 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 .build()));
3269 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3270 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3271
3272 // No more events
3273 leftWindow->assertNoEvents();
3274 rightWindow->assertNoEvents();
3275}
3276
3277/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003278 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3279 * While the touch is down, new hover events from the stylus device should be ignored. After the
3280 * touch is gone, stylus hovering should start working again.
3281 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003282TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDroppedWhenTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3284 sp<FakeWindowHandle> window =
3285 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3286 window->setFrame(Rect(0, 0, 200, 200));
3287
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003288 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003289
3290 const int32_t stylusDeviceId = 5;
3291 const int32_t touchDeviceId = 4;
3292 // Start hovering with stylus
3293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003295 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003296 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003298 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003299 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003300
3301 // Finger down on the window
3302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003303 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003304 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003305 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003306 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003307 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003308 // The touch device should cause hover to stop!
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003309 window->consumeMotionEvent(
3310 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3311 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003313 // Continue hovering with stylus.
3314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003315 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003316 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3317 AINPUT_SOURCE_STYLUS)
3318 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003319 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003320 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003321 // Hovers are now ignored
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003322
3323 // Lift up the finger
3324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003325 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003326 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3327 AINPUT_SOURCE_TOUCHSCREEN)
3328 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003329 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003331 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003332
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003334 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3336 AINPUT_SOURCE_STYLUS)
3337 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003338 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003340 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3341 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003342 window->assertNoEvents();
3343}
3344
3345/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003346 * A spy window above a window with no input channel.
3347 * Start hovering with a stylus device, and then tap with it.
3348 * Ensure spy window receives the entire sequence.
3349 */
3350TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3352 sp<FakeWindowHandle> spyWindow =
3353 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3354 spyWindow->setFrame(Rect(0, 0, 200, 200));
3355 spyWindow->setTrustedOverlay(true);
3356 spyWindow->setSpy(true);
3357 sp<FakeWindowHandle> window =
3358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3359 window->setNoInputChannel(true);
3360 window->setFrame(Rect(0, 0, 200, 200));
3361
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003362 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003363
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003364 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3367 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003368 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3369 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3372 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003373 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3374
3375 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003376 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3377 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3378 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003379 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3380
3381 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3384 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003385 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3386
3387 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3390 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003391 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3392 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3395 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003396 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3397
3398 // No more events
3399 spyWindow->assertNoEvents();
3400 window->assertNoEvents();
3401}
3402
3403/**
3404 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3405 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3406 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3407 * While the mouse is down, new move events from the touch device should be ignored.
3408 */
3409TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3411 sp<FakeWindowHandle> spyWindow =
3412 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3413 spyWindow->setFrame(Rect(0, 0, 200, 200));
3414 spyWindow->setTrustedOverlay(true);
3415 spyWindow->setSpy(true);
3416 sp<FakeWindowHandle> window =
3417 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3418 window->setFrame(Rect(0, 0, 200, 200));
3419
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003420 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003421
3422 const int32_t mouseDeviceId = 7;
3423 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003424
3425 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003426 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3427 .deviceId(mouseDeviceId)
3428 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3429 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003430 spyWindow->consumeMotionEvent(
3431 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3432 window->consumeMotionEvent(
3433 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3434
3435 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3437 .deviceId(touchDeviceId)
3438 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3439 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003440 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3441 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3442 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3443 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3444
Prabir Pradhan678438e2023-04-13 19:32:51 +00003445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3446 .deviceId(touchDeviceId)
3447 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3448 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003449 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3450 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3451
3452 // Pilfer the stream
3453 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3454 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3455
Prabir Pradhan678438e2023-04-13 19:32:51 +00003456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3457 .deviceId(touchDeviceId)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3459 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003460 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3461
3462 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3464 .deviceId(mouseDeviceId)
3465 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3466 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3467 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003468
3469 spyWindow->consumeMotionEvent(
3470 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3471 spyWindow->consumeMotionEvent(
3472 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3473 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3474
Prabir Pradhan678438e2023-04-13 19:32:51 +00003475 mDispatcher->notifyMotion(
3476 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3477 .deviceId(mouseDeviceId)
3478 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3479 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3480 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003482 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3483 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3484
3485 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3487 .deviceId(mouseDeviceId)
3488 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3489 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3490 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003491 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3492 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3493
3494 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3496 .deviceId(touchDeviceId)
3497 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3498 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003499
3500 // No more events
3501 spyWindow->assertNoEvents();
3502 window->assertNoEvents();
3503}
3504
3505/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003506 * On the display, have a single window, and also an area where there's no window.
3507 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3508 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3509 */
3510TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3512 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003513 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003514
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003515 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003516
3517 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003518 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003519
3520 mDispatcher->waitForIdle();
3521 window->assertNoEvents();
3522
3523 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003524 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003525 mDispatcher->waitForIdle();
3526 window->consumeMotionDown();
3527}
3528
3529/**
3530 * Same test as above, but instead of touching the empty space, the first touch goes to
3531 * non-touchable window.
3532 */
3533TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3535 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003536 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003537 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3538 window1->setTouchable(false);
3539 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003540 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003541 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3542
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003543 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003544
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003545 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003546 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003547
3548 mDispatcher->waitForIdle();
3549 window1->assertNoEvents();
3550 window2->assertNoEvents();
3551
3552 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003553 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003554 mDispatcher->waitForIdle();
3555 window2->consumeMotionDown();
3556}
3557
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003558/**
3559 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3560 * to the event time of the first ACTION_DOWN sent to the particular window.
3561 */
3562TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3564 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003565 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003566 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3567 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003568 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003569 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3570
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003571 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003572
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003573 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003574 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003575
3576 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003577
3578 MotionEvent* motionEvent1 = window1->consumeMotion();
3579 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003580 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003581 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3582 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003583
3584 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003585 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003586 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003587 MotionEvent* motionEvent2 = window2->consumeMotion();
3588 ASSERT_NE(motionEvent2, nullptr);
3589 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003590 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003592
3593 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003594 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003595 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003596 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003597
3598 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003599 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003600 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003601 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602
3603 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3604 window1->consumeMotionMove();
3605 window1->assertNoEvents();
3606
3607 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003608 mDispatcher->notifyMotion(
3609 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003610 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003611 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003612
Prabir Pradhan678438e2023-04-13 19:32:51 +00003613 mDispatcher->notifyMotion(
3614 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003615 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003616 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003617}
3618
Garfield Tandf26e862020-07-01 20:18:19 -07003619TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003621 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003622 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003623 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003624 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003625 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003626 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003627
3628 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3629
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003630 mDispatcher->onWindowInfosChanged(
3631 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003632
3633 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003635 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003636 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3637 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003638 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003639 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003640 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003641
3642 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003644 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003645 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3646 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003647 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003648 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003649 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3650 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003651
3652 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003655 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3656 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003657 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003658 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003659 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3660 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003661
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003663 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003664 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3665 AINPUT_SOURCE_MOUSE)
3666 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3667 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003668 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003669 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003670 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003671
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003673 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003674 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3675 AINPUT_SOURCE_MOUSE)
3676 .buttonState(0)
3677 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003678 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003679 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003680 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003681
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003683 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003684 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3685 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003686 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003687 .build()));
3688 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3689
3690 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003692 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003693 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3694 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003695 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003696 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003697 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003698
3699 // No more events
3700 windowLeft->assertNoEvents();
3701 windowRight->assertNoEvents();
3702}
3703
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003704/**
3705 * Put two fingers down (and don't release them) and click the mouse button.
3706 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3707 * currently active gesture should be canceled, and the new one should proceed.
3708 */
3709TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3711 sp<FakeWindowHandle> window =
3712 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3713 window->setFrame(Rect(0, 0, 600, 800));
3714
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003715 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003716
3717 const int32_t touchDeviceId = 4;
3718 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003719
3720 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3722 .deviceId(touchDeviceId)
3723 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3724 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003725
Prabir Pradhan678438e2023-04-13 19:32:51 +00003726 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3727 .deviceId(touchDeviceId)
3728 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3729 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3730 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003731 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3732 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3733
3734 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3736 .deviceId(mouseDeviceId)
3737 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3739 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003740 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3741 WithPointerCount(2u)));
3742 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3743
Prabir Pradhan678438e2023-04-13 19:32:51 +00003744 mDispatcher->notifyMotion(
3745 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3746 .deviceId(mouseDeviceId)
3747 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3748 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3749 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3750 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003751 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3752
3753 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3754 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3756 .deviceId(touchDeviceId)
3757 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3758 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003760 window->assertNoEvents();
3761}
3762
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003763TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3765
3766 sp<FakeWindowHandle> spyWindow =
3767 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3768 spyWindow->setFrame(Rect(0, 0, 600, 800));
3769 spyWindow->setTrustedOverlay(true);
3770 spyWindow->setSpy(true);
3771 sp<FakeWindowHandle> window =
3772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3773 window->setFrame(Rect(0, 0, 600, 800));
3774
3775 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003776 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003777
3778 // Send mouse cursor to the window
3779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003780 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003781 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3782 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003784 .build()));
3785
3786 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3787 WithSource(AINPUT_SOURCE_MOUSE)));
3788 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3789 WithSource(AINPUT_SOURCE_MOUSE)));
3790
3791 window->assertNoEvents();
3792 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003793}
3794
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003795TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3797
3798 sp<FakeWindowHandle> spyWindow =
3799 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3800 spyWindow->setFrame(Rect(0, 0, 600, 800));
3801 spyWindow->setTrustedOverlay(true);
3802 spyWindow->setSpy(true);
3803 sp<FakeWindowHandle> window =
3804 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3805 window->setFrame(Rect(0, 0, 600, 800));
3806
3807 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003808 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003809
3810 // Send mouse cursor to the window
3811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003812 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003813 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3814 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003815 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003816 .build()));
3817
3818 // Move mouse cursor
3819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003820 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003821 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3822 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003823 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003824 .build()));
3825
3826 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3827 WithSource(AINPUT_SOURCE_MOUSE)));
3828 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3829 WithSource(AINPUT_SOURCE_MOUSE)));
3830 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3831 WithSource(AINPUT_SOURCE_MOUSE)));
3832 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3833 WithSource(AINPUT_SOURCE_MOUSE)));
3834 // Touch down on the window
3835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003836 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003837 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3838 AINPUT_SOURCE_TOUCHSCREEN)
3839 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003841 .build()));
3842 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3843 WithSource(AINPUT_SOURCE_MOUSE)));
3844 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3845 WithSource(AINPUT_SOURCE_MOUSE)));
3846 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3847 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3848 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3849 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3850
3851 // pilfer the motion, retaining the gesture on the spy window.
3852 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3853 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3854 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3855
3856 // Touch UP on the window
3857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003858 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003859 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3860 AINPUT_SOURCE_TOUCHSCREEN)
3861 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003862 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003863 .build()));
3864 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3865 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3866
3867 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3868 // to send a new gesture. It should again go to both windows (spy and the window below), just
3869 // like the first gesture did, before pilfering. The window configuration has not changed.
3870
3871 // One more tap - DOWN
3872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003873 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003874 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3875 AINPUT_SOURCE_TOUCHSCREEN)
3876 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003877 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003878 .build()));
3879 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3880 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3881 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3882 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3883
3884 // Touch UP on the window
3885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003886 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003887 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3888 AINPUT_SOURCE_TOUCHSCREEN)
3889 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003890 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003891 .build()));
3892 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3893 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3894 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3895 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3896
3897 window->assertNoEvents();
3898 spyWindow->assertNoEvents();
3899}
3900
Garfield Tandf26e862020-07-01 20:18:19 -07003901// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3902// directly in this test.
3903TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003905 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003906 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003907 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003908
3909 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3910
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003911 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003912
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003914 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003915 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3916 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003917 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003918 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003919 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003920 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003922 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003923 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3924 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003925 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003926 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003927 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3928 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003929
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003931 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003932 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3933 AINPUT_SOURCE_MOUSE)
3934 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3935 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003936 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003937 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003938 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003939
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003941 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003942 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3943 AINPUT_SOURCE_MOUSE)
3944 .buttonState(0)
3945 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003946 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003947 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003948 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003949
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003951 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003952 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3953 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003954 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003955 .build()));
3956 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3957
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003958 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3959 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3960 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003961 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003962 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3963 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003964 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003965 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003966 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003967}
3968
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003969/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003970 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3971 * is generated.
3972 */
3973TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3975 sp<FakeWindowHandle> window =
3976 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3977 window->setFrame(Rect(0, 0, 1200, 800));
3978
3979 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3980
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003981 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003982
3983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003984 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003985 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3986 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003987 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003988 .build()));
3989 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3990
3991 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003992 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003993 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3994}
3995
3996/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003997 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3998 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003999TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4000 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4001 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4003 sp<FakeWindowHandle> window =
4004 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4005 window->setFrame(Rect(0, 0, 1200, 800));
4006
4007 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4008
4009 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4010
4011 MotionEventBuilder hoverEnterBuilder =
4012 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4013 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4014 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4016 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4018 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4019 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4020 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4021}
4022
4023/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004024 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4025 */
4026TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4028 sp<FakeWindowHandle> window =
4029 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4030 window->setFrame(Rect(0, 0, 100, 100));
4031
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004032 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004033
4034 const int32_t mouseDeviceId = 7;
4035 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004036
4037 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4039 .deviceId(mouseDeviceId)
4040 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4041 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004042 window->consumeMotionEvent(
4043 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4044
4045 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4047 .deviceId(touchDeviceId)
4048 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4049 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004050
4051 window->consumeMotionEvent(
4052 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4053 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4054}
4055
4056/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004057 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004058 * The tap causes a HOVER_EXIT event to be generated because the current event
4059 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004060 */
4061TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4062 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4063 sp<FakeWindowHandle> window =
4064 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4065 window->setFrame(Rect(0, 0, 100, 100));
4066
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004067 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4069 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4070 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004071 ASSERT_NO_FATAL_FAILURE(
4072 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4073 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004074
4075 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4077 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4078 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004079 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004080 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4081 WithSource(AINPUT_SOURCE_MOUSE))));
4082
4083 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004084 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4085 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4086
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004087 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4088 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4089 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004090 ASSERT_NO_FATAL_FAILURE(
4091 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4092 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4093}
4094
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004095TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4097 sp<FakeWindowHandle> windowDefaultDisplay =
4098 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4099 ADISPLAY_ID_DEFAULT);
4100 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4101 sp<FakeWindowHandle> windowSecondDisplay =
4102 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4103 SECOND_DISPLAY_ID);
4104 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4105
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004106 mDispatcher->onWindowInfosChanged(
4107 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004108
4109 // Set cursor position in window in default display and check that hover enter and move
4110 // events are generated.
4111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004112 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004113 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4114 AINPUT_SOURCE_MOUSE)
4115 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004116 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004117 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004118 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004119
4120 // Remove all windows in secondary display and check that no event happens on window in
4121 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004122 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4123
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004124 windowDefaultDisplay->assertNoEvents();
4125
4126 // Move cursor position in window in default display and check that only hover move
4127 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004128 mDispatcher->onWindowInfosChanged(
4129 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004131 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004132 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4133 AINPUT_SOURCE_MOUSE)
4134 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004135 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004136 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004137 windowDefaultDisplay->consumeMotionEvent(
4138 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4139 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004140 windowDefaultDisplay->assertNoEvents();
4141}
4142
Garfield Tan00f511d2019-06-12 16:55:40 -07004143TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004145
4146 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004147 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004148 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004149 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004150 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004151 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004152
4153 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4154
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004155 mDispatcher->onWindowInfosChanged(
4156 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004157
4158 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4159 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004161 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004162 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004163 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004164 windowRight->assertNoEvents();
4165}
4166
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004167TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004169 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4170 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004171 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004173 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004174 setFocusedWindow(window);
4175
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004176 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004177
Prabir Pradhan678438e2023-04-13 19:32:51 +00004178 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004179
4180 // Window should receive key down event.
4181 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4182
4183 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4184 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004186 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004187 AKEY_EVENT_FLAG_CANCELED);
4188}
4189
4190TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004192 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4193 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004196
Prabir Pradhan678438e2023-04-13 19:32:51 +00004197 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4198 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004199
4200 // Window should receive motion down event.
4201 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4202
4203 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4204 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004205 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004206 window->consumeMotionEvent(
4207 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004208}
4209
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004210TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4212 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4213 "Fake Window", ADISPLAY_ID_DEFAULT);
4214
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004215 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004216
4217 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4218 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4219 .build());
4220
4221 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4222
4223 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4224 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4226
4227 // After the device has been reset, a new hovering stream can be sent to the window
4228 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4230 .build());
4231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4232}
4233
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004234TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004236 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4237 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004238 window->setFocusable(true);
4239
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004240 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004241 setFocusedWindow(window);
4242
4243 window->consumeFocusEvent(true);
4244
Prabir Pradhan678438e2023-04-13 19:32:51 +00004245 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004246 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4247 const nsecs_t injectTime = keyArgs.eventTime;
4248 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004249 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004250 // The dispatching time should be always greater than or equal to intercept key timeout.
4251 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4252 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4253 std::chrono::nanoseconds(interceptKeyTimeout).count());
4254}
4255
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004256/**
4257 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4258 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004259TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004261 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4262 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004263 window->setFocusable(true);
4264
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004265 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004266 setFocusedWindow(window);
4267
4268 window->consumeFocusEvent(true);
4269
Prabir Pradhan678438e2023-04-13 19:32:51 +00004270 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004272
4273 // Set a value that's significantly larger than the default consumption timeout. If the
4274 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4275 mFakePolicy->setInterceptKeyTimeout(600ms);
4276 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4277 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004278 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4279}
4280
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004281/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004282 * Two windows. First is a regular window. Second does not overlap with the first, and has
4283 * WATCH_OUTSIDE_TOUCH.
4284 * Both windows are owned by the same UID.
4285 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4286 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4287 */
4288TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004290 sp<FakeWindowHandle> window =
4291 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004292 window->setFrame(Rect{0, 0, 100, 100});
4293
4294 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004295 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004296 ADISPLAY_ID_DEFAULT);
4297 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4298 outsideWindow->setWatchOutsideTouch(true);
4299 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004300 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004301
4302 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004303 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4304 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4305 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004306 window->consumeMotionDown();
4307 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4308 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4309 outsideWindow->consumeMotionEvent(
4310 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4311}
4312
4313/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004314 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4315 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4316 * ACTION_OUTSIDE event is sent per gesture.
4317 */
4318TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4319 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004321 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4322 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004323 window->setWatchOutsideTouch(true);
4324 window->setFrame(Rect{0, 0, 100, 100});
4325 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4327 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004328 secondWindow->setFrame(Rect{100, 100, 200, 200});
4329 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004330 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4331 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004332 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004333 mDispatcher->onWindowInfosChanged(
4334 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004335
4336 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004337 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4338 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4339 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004340 window->assertNoEvents();
4341 secondWindow->assertNoEvents();
4342
4343 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4344 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004345 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4346 ADISPLAY_ID_DEFAULT,
4347 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004348 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4349 window->consumeMotionEvent(
4350 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004351 secondWindow->consumeMotionDown();
4352 thirdWindow->assertNoEvents();
4353
4354 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4355 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004356 mDispatcher->notifyMotion(
4357 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4358 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004359 window->assertNoEvents();
4360 secondWindow->consumeMotionMove();
4361 thirdWindow->consumeMotionDown();
4362}
4363
Prabir Pradhan814fe082022-07-22 20:22:18 +00004364TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004366 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4367 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004368 window->setFocusable(true);
4369
Patrick Williamsd828f302023-04-28 17:52:08 -05004370 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004371 setFocusedWindow(window);
4372
4373 window->consumeFocusEvent(true);
4374
Prabir Pradhan678438e2023-04-13 19:32:51 +00004375 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4376 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4377 mDispatcher->notifyKey(keyDown);
4378 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004379
4380 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4381 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4382
4383 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004384 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004385
4386 window->consumeFocusEvent(false);
4387
Prabir Pradhan678438e2023-04-13 19:32:51 +00004388 mDispatcher->notifyKey(keyDown);
4389 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004390 window->assertNoEvents();
4391}
4392
Arthur Hung96483742022-11-15 03:30:48 +00004393TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4396 "Fake Window", ADISPLAY_ID_DEFAULT);
4397 // Ensure window is non-split and have some transform.
4398 window->setPreventSplitting(true);
4399 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004400 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004401
4402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004403 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004404 {50, 50}))
4405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4406 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4407
4408 const MotionEvent secondFingerDownEvent =
4409 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4410 .displayId(ADISPLAY_ID_DEFAULT)
4411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004414 .build();
4415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004416 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004417 InputEventInjectionSync::WAIT_FOR_RESULT))
4418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4419
4420 const MotionEvent* event = window->consumeMotion();
4421 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4422 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4423 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4424 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4425 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4426}
4427
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004428/**
4429 * Two windows: a splittable and a non-splittable.
4430 * The non-splittable window shouldn't receive any "incomplete" gestures.
4431 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4432 * The second pointer should be dropped because the initial window is splittable, so it won't get
4433 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4434 * "incomplete" gestures.
4435 */
4436TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4438 sp<FakeWindowHandle> leftWindow =
4439 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4440 ADISPLAY_ID_DEFAULT);
4441 leftWindow->setPreventSplitting(false);
4442 leftWindow->setFrame(Rect(0, 0, 100, 100));
4443 sp<FakeWindowHandle> rightWindow =
4444 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4445 ADISPLAY_ID_DEFAULT);
4446 rightWindow->setPreventSplitting(true);
4447 rightWindow->setFrame(Rect(100, 100, 200, 200));
4448 mDispatcher->onWindowInfosChanged(
4449 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4450
4451 // Touch down on left, splittable window
4452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4453 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4454 .build());
4455 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4456
4457 mDispatcher->notifyMotion(
4458 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4459 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4460 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4461 .build());
4462 leftWindow->assertNoEvents();
4463 rightWindow->assertNoEvents();
4464}
4465
Harry Cuttsb166c002023-05-09 13:06:05 +00004466TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4468 sp<FakeWindowHandle> window =
4469 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4470 window->setFrame(Rect(0, 0, 400, 400));
4471 sp<FakeWindowHandle> trustedOverlay =
4472 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4473 ADISPLAY_ID_DEFAULT);
4474 trustedOverlay->setSpy(true);
4475 trustedOverlay->setTrustedOverlay(true);
4476
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004477 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004478
4479 // Start a three-finger touchpad swipe
4480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4481 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4482 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4483 .build());
4484 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4485 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4486 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4487 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4488 .build());
4489 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4490 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4491 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4492 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4493 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4494 .build());
4495
4496 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4497 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4498 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4499
4500 // Move the swipe a bit
4501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4502 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4503 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4504 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4505 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4506 .build());
4507
4508 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4509
4510 // End the swipe
4511 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4512 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4513 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4514 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4515 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4516 .build());
4517 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4518 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4519 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4520 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4521 .build());
4522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4523 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4524 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4525 .build());
4526
4527 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4528 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4529 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4530
4531 window->assertNoEvents();
4532}
4533
4534TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4536 sp<FakeWindowHandle> window =
4537 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4538 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004539 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004540
4541 // Start a three-finger touchpad swipe
4542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4543 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4544 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4545 .build());
4546 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4547 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4548 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4549 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4550 .build());
4551 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4552 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4553 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4554 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4555 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4556 .build());
4557
4558 // Move the swipe a bit
4559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4560 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4561 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4562 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4563 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4564 .build());
4565
4566 // End the swipe
4567 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4568 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4569 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4570 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4571 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4572 .build());
4573 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4574 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4575 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4576 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4577 .build());
4578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4579 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4580 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4581 .build());
4582
4583 window->assertNoEvents();
4584}
4585
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004586/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004587 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4588 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004589 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004590 */
4591TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4592 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4593 sp<FakeWindowHandle> window =
4594 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4595 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004596 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004597
4598 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4600 .downTime(baseTime + 10)
4601 .eventTime(baseTime + 10)
4602 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4603 .build());
4604
4605 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4606
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004607 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004608 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004609
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004610 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004611
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004612 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4613 .downTime(baseTime + 10)
4614 .eventTime(baseTime + 30)
4615 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4616 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4617 .build());
4618
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004619 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4620
4621 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004622 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4623 .downTime(baseTime + 10)
4624 .eventTime(baseTime + 40)
4625 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4626 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4627 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004628
4629 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4630
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4632 .downTime(baseTime + 10)
4633 .eventTime(baseTime + 50)
4634 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4635 .build());
4636
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004637 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4638
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4640 .downTime(baseTime + 60)
4641 .eventTime(baseTime + 60)
4642 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4643 .build());
4644
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004645 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004646}
4647
4648/**
Hu Guo771a7692023-09-17 20:51:08 +08004649 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4650 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4651 * its coordinates should be converted by the transform of the windows of target screen.
4652 */
4653TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4654 // This case will create a window and a spy window on the default display and mirror
4655 // window on the second display. cancel event is sent through spy window pilferPointers
4656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4657
4658 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4659 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4660 spyWindowDefaultDisplay->setTrustedOverlay(true);
4661 spyWindowDefaultDisplay->setSpy(true);
4662
4663 sp<FakeWindowHandle> windowDefaultDisplay =
4664 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4665 ADISPLAY_ID_DEFAULT);
4666 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4667
4668 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4669 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4670
4671 // Add the windows to the dispatcher
4672 mDispatcher->onWindowInfosChanged(
4673 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4674 *windowSecondDisplay->getInfo()},
4675 {},
4676 0,
4677 0});
4678
4679 // Send down to ADISPLAY_ID_DEFAULT
4680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4682 {100, 100}))
4683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4684
4685 spyWindowDefaultDisplay->consumeMotionDown();
4686 windowDefaultDisplay->consumeMotionDown();
4687
4688 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4689
4690 // windowDefaultDisplay gets cancel
4691 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4692 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4693
4694 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4695 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4696 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4697 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4698 EXPECT_EQ(100, event->getX(0));
4699 EXPECT_EQ(100, event->getY(0));
4700}
4701
4702/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004703 * Ensure the correct coordinate spaces are used by InputDispatcher.
4704 *
4705 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4706 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4707 * space.
4708 */
4709class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4710public:
4711 void SetUp() override {
4712 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004713 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004714 }
4715
4716 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4717 gui::DisplayInfo info;
4718 info.displayId = displayId;
4719 info.transform = transform;
4720 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004721 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004722 }
4723
4724 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4725 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004726 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004727 }
4728
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004729 void removeAllWindowsAndDisplays() {
4730 mDisplayInfos.clear();
4731 mWindowInfos.clear();
4732 }
4733
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004734 // Set up a test scenario where the display has a scaled projection and there are two windows
4735 // on the display.
4736 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4737 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4738 // respectively.
4739 ui::Transform displayTransform;
4740 displayTransform.set(2, 0, 0, 4);
4741 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4742
4743 std::shared_ptr<FakeApplicationHandle> application =
4744 std::make_shared<FakeApplicationHandle>();
4745
4746 // Add two windows to the display. Their frames are represented in the display space.
4747 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004748 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4749 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004750 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4751 addWindow(firstWindow);
4752
4753 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004754 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4755 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004756 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4757 addWindow(secondWindow);
4758 return {std::move(firstWindow), std::move(secondWindow)};
4759 }
4760
4761private:
4762 std::vector<gui::DisplayInfo> mDisplayInfos;
4763 std::vector<gui::WindowInfo> mWindowInfos;
4764};
4765
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004766TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004767 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4768 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004769 // selected so that if the hit test was performed with the point and the bounds being in
4770 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004771 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4772 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4773 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004774
4775 firstWindow->consumeMotionDown();
4776 secondWindow->assertNoEvents();
4777}
4778
4779// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4780// the event should be treated as being in the logical display space.
4781TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4782 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4783 // Send down to the first window. The point is represented in the logical display space. The
4784 // point is selected so that if the hit test was done in logical display space, then it would
4785 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004787 PointF{75 * 2, 55 * 4});
4788
4789 firstWindow->consumeMotionDown();
4790 secondWindow->assertNoEvents();
4791}
4792
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004793// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4794// event should be treated as being in the logical display space.
4795TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4796 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4797
4798 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4799 ui::Transform injectedEventTransform;
4800 injectedEventTransform.set(matrix);
4801 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4802 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4803
4804 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4805 .displayId(ADISPLAY_ID_DEFAULT)
4806 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004807 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004808 .x(untransformedPoint.x)
4809 .y(untransformedPoint.y))
4810 .build();
4811 event.transform(matrix);
4812
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004813 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004814 InputEventInjectionSync::WAIT_FOR_RESULT);
4815
4816 firstWindow->consumeMotionDown();
4817 secondWindow->assertNoEvents();
4818}
4819
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004820TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4821 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4822
4823 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004824 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4825 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4826 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004827
4828 firstWindow->assertNoEvents();
4829 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004830 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004831 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4832
4833 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4834 EXPECT_EQ(300, event->getRawX(0));
4835 EXPECT_EQ(880, event->getRawY(0));
4836
4837 // Ensure that the x and y values are in the window's coordinate space.
4838 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4839 // the logical display space. This will be the origin of the window space.
4840 EXPECT_EQ(100, event->getX(0));
4841 EXPECT_EQ(80, event->getY(0));
4842}
4843
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004844TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4845 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4846 // The monitor will always receive events in the logical display's coordinate space, because
4847 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004848 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004849
4850 // Send down to the first window.
4851 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4852 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4853 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4854 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4855
4856 // Second pointer goes down on second window.
4857 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4858 ADISPLAY_ID_DEFAULT,
4859 {PointF{50, 100}, PointF{150, 220}}));
4860 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4861 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4862 {1, PointF{300, 880}}};
4863 monitor.consumeMotionEvent(
4864 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4865
4866 mDispatcher->cancelCurrentTouch();
4867
4868 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4869 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4870 monitor.consumeMotionEvent(
4871 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4872}
4873
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004874TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4875 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4876
4877 // Send down to the first window.
4878 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4879 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4880 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4881
4882 // The pointer is transferred to the second window, and the second window receives it in the
4883 // correct coordinate space.
4884 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4885 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4886 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4887}
4888
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004889TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4890 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4891
4892 // Send hover move to the second window, and ensure it shows up as hover enter.
4893 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4894 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4895 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4896 WithCoords(100, 80), WithRawCoords(300, 880)));
4897
4898 // Touch down at the same location and ensure a hover exit is synthesized.
4899 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4900 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4901 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4902 WithRawCoords(300, 880)));
4903 secondWindow->consumeMotionEvent(
4904 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4905 secondWindow->assertNoEvents();
4906 firstWindow->assertNoEvents();
4907}
4908
Prabir Pradhan453ae732023-10-13 14:30:14 +00004909// Same as above, but while the window is being mirrored.
4910TEST_F(InputDispatcherDisplayProjectionTest,
4911 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4912 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4913
4914 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4915 ui::Transform secondDisplayTransform;
4916 secondDisplayTransform.set(matrix);
4917 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4918
4919 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4920 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4921 addWindow(secondWindowClone);
4922
4923 // Send hover move to the second window, and ensure it shows up as hover enter.
4924 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4925 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4926 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4927 WithCoords(100, 80), WithRawCoords(300, 880)));
4928
4929 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4930 // display.
4931 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4932 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4933 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4934 WithRawCoords(300, 880)));
4935 secondWindow->consumeMotionEvent(
4936 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4937 secondWindow->assertNoEvents();
4938 firstWindow->assertNoEvents();
4939}
4940
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004941TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4942 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4943
4944 // Send hover enter to second window
4945 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4946 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4947 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4948 WithCoords(100, 80), WithRawCoords(300, 880)));
4949
4950 mDispatcher->cancelCurrentTouch();
4951
4952 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4953 WithRawCoords(300, 880)));
4954 secondWindow->assertNoEvents();
4955 firstWindow->assertNoEvents();
4956}
4957
Prabir Pradhan453ae732023-10-13 14:30:14 +00004958// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004959TEST_F(InputDispatcherDisplayProjectionTest,
4960 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4961 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4962
4963 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4964 ui::Transform secondDisplayTransform;
4965 secondDisplayTransform.set(matrix);
4966 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4967
4968 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4969 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4970 addWindow(secondWindowClone);
4971
4972 // Send hover enter to second window
4973 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4974 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4975 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4976 WithCoords(100, 80), WithRawCoords(300, 880),
4977 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4978
4979 mDispatcher->cancelCurrentTouch();
4980
4981 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4982 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4983 WithRawCoords(300, 880),
4984 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4985 secondWindow->assertNoEvents();
4986 firstWindow->assertNoEvents();
4987}
4988
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004989/** Ensure consistent behavior of InputDispatcher in all orientations. */
4990class InputDispatcherDisplayOrientationFixture
4991 : public InputDispatcherDisplayProjectionTest,
4992 public ::testing::WithParamInterface<ui::Rotation> {};
4993
4994// This test verifies the touchable region of a window for all rotations of the display by tapping
4995// in different locations on the display, specifically points close to the four corners of a
4996// window.
4997TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4998 constexpr static int32_t displayWidth = 400;
4999 constexpr static int32_t displayHeight = 800;
5000
5001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5002
5003 const auto rotation = GetParam();
5004
5005 // Set up the display with the specified rotation.
5006 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5007 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5008 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5009 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5010 logicalDisplayWidth, logicalDisplayHeight);
5011 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5012
5013 // Create a window with its bounds determined in the logical display.
5014 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5015 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5016 sp<FakeWindowHandle> window =
5017 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5018 window->setFrame(frameInDisplay, displayTransform);
5019 addWindow(window);
5020
5021 // The following points in logical display space should be inside the window.
5022 static const std::array<vec2, 4> insidePoints{
5023 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5024 for (const auto pointInsideWindow : insidePoints) {
5025 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5026 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005027 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5028 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5029 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005030 window->consumeMotionDown();
5031
Prabir Pradhan678438e2023-04-13 19:32:51 +00005032 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5033 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5034 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005035 window->consumeMotionUp();
5036 }
5037
5038 // The following points in logical display space should be outside the window.
5039 static const std::array<vec2, 5> outsidePoints{
5040 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5041 for (const auto pointOutsideWindow : outsidePoints) {
5042 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5043 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005044 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5045 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5046 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005047
Prabir Pradhan678438e2023-04-13 19:32:51 +00005048 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5049 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5050 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005051 }
5052 window->assertNoEvents();
5053}
5054
5055// Run the precision tests for all rotations.
5056INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5057 InputDispatcherDisplayOrientationFixture,
5058 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5059 ui::ROTATION_270),
5060 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5061 return ftl::enum_string(testParamInfo.param);
5062 });
5063
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005064using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5065 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005066
5067class TransferTouchFixture : public InputDispatcherTest,
5068 public ::testing::WithParamInterface<TransferFunction> {};
5069
5070TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005072
5073 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005074 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005075 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5076 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005077 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005078 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005079 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5080 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005081 sp<FakeWindowHandle> wallpaper =
5082 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5083 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005084 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005085 mDispatcher->onWindowInfosChanged(
5086 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005087
5088 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005089 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5090 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005091
Svet Ganov5d3bc372020-01-26 23:11:07 -08005092 // Only the first window should get the down event
5093 firstWindow->consumeMotionDown();
5094 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005095 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005096
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005097 // Transfer touch to the second window
5098 TransferFunction f = GetParam();
5099 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5100 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005101 // The first window gets cancel and the second gets down
5102 firstWindow->consumeMotionCancel();
5103 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005104 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005105
5106 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5108 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005109 // The first window gets no events and the second gets up
5110 firstWindow->assertNoEvents();
5111 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005112 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005113}
5114
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005115/**
5116 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5117 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5118 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5119 * natural to the user.
5120 * In this test, we are sending a pointer to both spy window and first window. We then try to
5121 * transfer touch to the second window. The dispatcher should identify the first window as the
5122 * one that should lose the gesture, and therefore the action should be to move the gesture from
5123 * the first window to the second.
5124 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5125 * the other API, as well.
5126 */
5127TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5128 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5129
5130 // Create a couple of windows + a spy window
5131 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005132 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005133 spyWindow->setTrustedOverlay(true);
5134 spyWindow->setSpy(true);
5135 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005136 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005137 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005138 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005139
5140 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005141 mDispatcher->onWindowInfosChanged(
5142 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005143
5144 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5146 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005147 // Only the first window and spy should get the down event
5148 spyWindow->consumeMotionDown();
5149 firstWindow->consumeMotionDown();
5150
5151 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5152 // if f === 'transferTouch'.
5153 TransferFunction f = GetParam();
5154 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5155 ASSERT_TRUE(success);
5156 // The first window gets cancel and the second gets down
5157 firstWindow->consumeMotionCancel();
5158 secondWindow->consumeMotionDown();
5159
5160 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005161 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5162 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005163 // The first window gets no events and the second+spy get up
5164 firstWindow->assertNoEvents();
5165 spyWindow->consumeMotionUp();
5166 secondWindow->consumeMotionUp();
5167}
5168
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005169TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005171
5172 PointF touchPoint = {10, 10};
5173
5174 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005175 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005176 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5177 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005178 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005179 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005180 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5181 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005182 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005183
5184 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005185 mDispatcher->onWindowInfosChanged(
5186 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005187
5188 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5190 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5191 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005192 // Only the first window should get the down event
5193 firstWindow->consumeMotionDown();
5194 secondWindow->assertNoEvents();
5195
5196 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005197 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5198 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005199 // Only the first window should get the pointer down event
5200 firstWindow->consumeMotionPointerDown(1);
5201 secondWindow->assertNoEvents();
5202
5203 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005204 TransferFunction f = GetParam();
5205 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5206 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005207 // The first window gets cancel and the second gets down and pointer down
5208 firstWindow->consumeMotionCancel();
5209 secondWindow->consumeMotionDown();
5210 secondWindow->consumeMotionPointerDown(1);
5211
5212 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005213 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5214 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005215 // The first window gets nothing and the second gets pointer up
5216 firstWindow->assertNoEvents();
5217 secondWindow->consumeMotionPointerUp(1);
5218
5219 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5221 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005222 // The first window gets nothing and the second gets up
5223 firstWindow->assertNoEvents();
5224 secondWindow->consumeMotionUp();
5225}
5226
Arthur Hungc539dbb2022-12-08 07:45:36 +00005227TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5229
5230 // Create a couple of windows
5231 sp<FakeWindowHandle> firstWindow =
5232 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5233 ADISPLAY_ID_DEFAULT);
5234 firstWindow->setDupTouchToWallpaper(true);
5235 sp<FakeWindowHandle> secondWindow =
5236 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5237 ADISPLAY_ID_DEFAULT);
5238 secondWindow->setDupTouchToWallpaper(true);
5239
5240 sp<FakeWindowHandle> wallpaper1 =
5241 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5242 wallpaper1->setIsWallpaper(true);
5243
5244 sp<FakeWindowHandle> wallpaper2 =
5245 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5246 wallpaper2->setIsWallpaper(true);
5247 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005248 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5249 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5250 {},
5251 0,
5252 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005253
5254 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005255 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5256 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005257
5258 // Only the first window should get the down event
5259 firstWindow->consumeMotionDown();
5260 secondWindow->assertNoEvents();
5261 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5262 wallpaper2->assertNoEvents();
5263
5264 // Transfer touch focus to the second window
5265 TransferFunction f = GetParam();
5266 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5267 ASSERT_TRUE(success);
5268
5269 // The first window gets cancel and the second gets down
5270 firstWindow->consumeMotionCancel();
5271 secondWindow->consumeMotionDown();
5272 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5273 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5274
5275 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5277 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005278 // The first window gets no events and the second gets up
5279 firstWindow->assertNoEvents();
5280 secondWindow->consumeMotionUp();
5281 wallpaper1->assertNoEvents();
5282 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5283}
5284
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005285// For the cases of single pointer touch and two pointers non-split touch, the api's
5286// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5287// for the case where there are multiple pointers split across several windows.
5288INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5289 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005290 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5291 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005292 return dispatcher->transferTouch(destChannelToken,
5293 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005294 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005295 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5296 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005297 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005298 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005299 }));
5300
Svet Ganov5d3bc372020-01-26 23:11:07 -08005301TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005303
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005304 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005305 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5306 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005307 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005308
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005309 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005310 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5311 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005312 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005313
5314 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005315 mDispatcher->onWindowInfosChanged(
5316 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005317
5318 PointF pointInFirst = {300, 200};
5319 PointF pointInSecond = {300, 600};
5320
5321 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005322 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5323 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5324 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005325 // Only the first window should get the down event
5326 firstWindow->consumeMotionDown();
5327 secondWindow->assertNoEvents();
5328
5329 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005330 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5331 ADISPLAY_ID_DEFAULT,
5332 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005333 // The first window gets a move and the second a down
5334 firstWindow->consumeMotionMove();
5335 secondWindow->consumeMotionDown();
5336
5337 // Transfer touch focus to the second window
5338 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5339 // The first window gets cancel and the new gets pointer down (it already saw down)
5340 firstWindow->consumeMotionCancel();
5341 secondWindow->consumeMotionPointerDown(1);
5342
5343 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005344 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5345 ADISPLAY_ID_DEFAULT,
5346 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005347 // The first window gets nothing and the second gets pointer up
5348 firstWindow->assertNoEvents();
5349 secondWindow->consumeMotionPointerUp(1);
5350
5351 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005352 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5353 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005354 // The first window gets nothing and the second gets up
5355 firstWindow->assertNoEvents();
5356 secondWindow->consumeMotionUp();
5357}
5358
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005359// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5360// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5361// touch is not supported, so the touch should continue on those windows and the transferred-to
5362// window should get nothing.
5363TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5365
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005366 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005367 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5368 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005369 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005370
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005371 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005372 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5373 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005374 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005375
5376 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005377 mDispatcher->onWindowInfosChanged(
5378 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005379
5380 PointF pointInFirst = {300, 200};
5381 PointF pointInSecond = {300, 600};
5382
5383 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5385 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5386 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005387 // Only the first window should get the down event
5388 firstWindow->consumeMotionDown();
5389 secondWindow->assertNoEvents();
5390
5391 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005392 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5393 ADISPLAY_ID_DEFAULT,
5394 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005395 // The first window gets a move and the second a down
5396 firstWindow->consumeMotionMove();
5397 secondWindow->consumeMotionDown();
5398
5399 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005400 const bool transferred =
5401 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005402 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5403 ASSERT_FALSE(transferred);
5404 firstWindow->assertNoEvents();
5405 secondWindow->assertNoEvents();
5406
5407 // The rest of the dispatch should proceed as normal
5408 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005409 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5410 ADISPLAY_ID_DEFAULT,
5411 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005412 // The first window gets MOVE and the second gets pointer up
5413 firstWindow->consumeMotionMove();
5414 secondWindow->consumeMotionUp();
5415
5416 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005417 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5418 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005419 // The first window gets nothing and the second gets up
5420 firstWindow->consumeMotionUp();
5421 secondWindow->assertNoEvents();
5422}
5423
Arthur Hungabbb9d82021-09-01 14:52:30 +00005424// This case will create two windows and one mirrored window on the default display and mirror
5425// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5426// the windows info of second display before default display.
5427TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5429 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005430 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005431 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005432 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005433 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005434 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005435
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005436 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005437 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005438
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005439 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005440 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005441
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005442 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005443 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005444
5445 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005446 mDispatcher->onWindowInfosChanged(
5447 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5448 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5449 *secondWindowInPrimary->getInfo()},
5450 {},
5451 0,
5452 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005453
5454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005455 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005456 {50, 50}))
5457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5458
5459 // Window should receive motion event.
5460 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5461
5462 // Transfer touch focus
5463 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5464 secondWindowInPrimary->getToken()));
5465 // The first window gets cancel.
5466 firstWindowInPrimary->consumeMotionCancel();
5467 secondWindowInPrimary->consumeMotionDown();
5468
5469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005470 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005471 ADISPLAY_ID_DEFAULT, {150, 50}))
5472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5473 firstWindowInPrimary->assertNoEvents();
5474 secondWindowInPrimary->consumeMotionMove();
5475
5476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005477 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005478 {150, 50}))
5479 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5480 firstWindowInPrimary->assertNoEvents();
5481 secondWindowInPrimary->consumeMotionUp();
5482}
5483
5484// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5485// 'transferTouch' api.
5486TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5487 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5488 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005489 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005490 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005491 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005493 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005494
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005495 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005496 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005497
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005498 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005499 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005500
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005501 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005502 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005503
5504 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005505 mDispatcher->onWindowInfosChanged(
5506 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5507 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5508 *secondWindowInPrimary->getInfo()},
5509 {},
5510 0,
5511 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512
5513 // Touch on second display.
5514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5516 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5518
5519 // Window should receive motion event.
5520 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5521
5522 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005523 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005524
5525 // The first window gets cancel.
5526 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5527 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5528
5529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005530 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005531 SECOND_DISPLAY_ID, {150, 50}))
5532 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5533 firstWindowInPrimary->assertNoEvents();
5534 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5535
5536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005537 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5539 firstWindowInPrimary->assertNoEvents();
5540 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5541}
5542
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005543TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005544 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005545 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5546 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005547
Vishnu Nair47074b82020-08-14 11:54:47 -07005548 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005549 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005550 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005551
5552 window->consumeFocusEvent(true);
5553
Prabir Pradhan678438e2023-04-13 19:32:51 +00005554 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005555
5556 // Window should receive key down event.
5557 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005558
5559 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005560 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005561 mFakePolicy->assertUserActivityPoked();
5562}
5563
5564TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5566 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5567 "Fake Window", ADISPLAY_ID_DEFAULT);
5568
5569 window->setDisableUserActivity(true);
5570 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005571 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005572 setFocusedWindow(window);
5573
5574 window->consumeFocusEvent(true);
5575
5576 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5577
5578 // Window should receive key down event.
5579 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5580
5581 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005582 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005583 mFakePolicy->assertUserActivityNotPoked();
5584}
5585
5586TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5588 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5589 "Fake Window", ADISPLAY_ID_DEFAULT);
5590
5591 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005592 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005593 setFocusedWindow(window);
5594
5595 window->consumeFocusEvent(true);
5596
5597 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5598 mDispatcher->waitForIdle();
5599
5600 // System key is not passed down
5601 window->assertNoEvents();
5602
5603 // Should have poked user activity
5604 mFakePolicy->assertUserActivityPoked();
5605}
5606
5607TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5609 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5610 "Fake Window", ADISPLAY_ID_DEFAULT);
5611
5612 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005613 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005614 setFocusedWindow(window);
5615
5616 window->consumeFocusEvent(true);
5617
5618 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5619 mDispatcher->waitForIdle();
5620
5621 // System key is not passed down
5622 window->assertNoEvents();
5623
5624 // Should have poked user activity
5625 mFakePolicy->assertUserActivityPoked();
5626}
5627
5628TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5631 "Fake Window", ADISPLAY_ID_DEFAULT);
5632
5633 window->setDisableUserActivity(true);
5634 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005635 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005636 setFocusedWindow(window);
5637
5638 window->consumeFocusEvent(true);
5639
5640 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5641 mDispatcher->waitForIdle();
5642
5643 // System key is not passed down
5644 window->assertNoEvents();
5645
5646 // Should have poked user activity
5647 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005648}
5649
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005650TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5652 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5653 "Fake Window", ADISPLAY_ID_DEFAULT);
5654
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005655 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005656
5657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005659 ADISPLAY_ID_DEFAULT, {100, 100}))
5660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5661
5662 window->consumeMotionEvent(
5663 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5664
5665 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005666 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005667 mFakePolicy->assertUserActivityPoked();
5668}
5669
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005670TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5673 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005674
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005676
Prabir Pradhan678438e2023-04-13 19:32:51 +00005677 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005678 mDispatcher->waitForIdle();
5679
5680 window->assertNoEvents();
5681}
5682
5683// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5684TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5687 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005689 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005690
5691 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005692 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005693 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005694 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5695 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005696
5697 // Window should receive only the motion event
5698 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5699 window->assertNoEvents(); // Key event or focus event will not be received
5700}
5701
arthurhungea3f4fc2020-12-21 23:18:53 +08005702TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5704
arthurhungea3f4fc2020-12-21 23:18:53 +08005705 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005706 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5707 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005708 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005709
arthurhungea3f4fc2020-12-21 23:18:53 +08005710 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005711 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5712 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005713 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005714
5715 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005716 mDispatcher->onWindowInfosChanged(
5717 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005718
5719 PointF pointInFirst = {300, 200};
5720 PointF pointInSecond = {300, 600};
5721
5722 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005723 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5724 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5725 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005726 // Only the first window should get the down event
5727 firstWindow->consumeMotionDown();
5728 secondWindow->assertNoEvents();
5729
5730 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005731 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5732 ADISPLAY_ID_DEFAULT,
5733 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005734 // The first window gets a move and the second a down
5735 firstWindow->consumeMotionMove();
5736 secondWindow->consumeMotionDown();
5737
5738 // Send pointer cancel to the second window
5739 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005740 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005741 {pointInFirst, pointInSecond});
5742 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005743 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005744 // The first window gets move and the second gets cancel.
5745 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5746 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5747
5748 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005749 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5750 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005751 // The first window gets up and the second gets nothing.
5752 firstWindow->consumeMotionUp();
5753 secondWindow->assertNoEvents();
5754}
5755
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005756TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5758
5759 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005760 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005761 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005762 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5763 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5764 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5765
Harry Cutts33476232023-01-30 19:57:29 +00005766 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005767 window->assertNoEvents();
5768 mDispatcher->waitForIdle();
5769}
5770
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005771using InputDispatcherMonitorTest = InputDispatcherTest;
5772
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005773/**
5774 * Two entities that receive touch: A window, and a global monitor.
5775 * The touch goes to the window, and then the window disappears.
5776 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5777 * for the monitor, as well.
5778 * 1. foregroundWindow
5779 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5780 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005781TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5783 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005784 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005785
Prabir Pradhanfb549072023-10-05 19:17:36 +00005786 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005787
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005788 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005790 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005791 {100, 200}))
5792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5793
5794 // Both the foreground window and the global monitor should receive the touch down
5795 window->consumeMotionDown();
5796 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5797
5798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005799 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005800 ADISPLAY_ID_DEFAULT, {110, 200}))
5801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5802
5803 window->consumeMotionMove();
5804 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5805
5806 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005807 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005808 window->consumeMotionCancel();
5809 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5810
5811 // If more events come in, there will be no more foreground window to send them to. This will
5812 // cause a cancel for the monitor, as well.
5813 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005814 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005815 ADISPLAY_ID_DEFAULT, {120, 200}))
5816 << "Injection should fail because the window was removed";
5817 window->assertNoEvents();
5818 // Global monitor now gets the cancel
5819 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5820}
5821
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005822TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005824 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5825 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005826 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005827
Prabir Pradhanfb549072023-10-05 19:17:36 +00005828 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005829
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005831 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005833 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005834 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005835}
5836
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005837TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005838 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005839
Chris Yea209fde2020-07-22 13:54:51 -07005840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005841 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5842 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005844
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005846 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005848 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005849 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005850
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005851 // Pilfer pointers from the monitor.
5852 // This should not do anything and the window should continue to receive events.
5853 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005854
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005856 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005857 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005859
5860 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5861 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005862}
5863
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005864TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005865 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005866 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5867 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005868 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005869 window->setWindowOffset(20, 40);
5870 window->setWindowTransform(0, 1, -1, 0);
5871
Prabir Pradhanfb549072023-10-05 19:17:36 +00005872 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005873
5874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005875 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5877 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5878 MotionEvent* event = monitor.consumeMotion();
5879 // Even though window has transform, gesture monitor must not.
5880 ASSERT_EQ(ui::Transform(), event->getTransform());
5881}
5882
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005883TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005885 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005886
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005887 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005888 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005889 << "Injection should fail if there is a monitor, but no touchable window";
5890 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005891}
5892
chaviw81e2bb92019-12-18 15:03:51 -08005893TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005895 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5896 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005899
5900 NotifyMotionArgs motionArgs =
5901 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5902 ADISPLAY_ID_DEFAULT);
5903
Prabir Pradhan678438e2023-04-13 19:32:51 +00005904 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005905 // Window should receive motion down event.
5906 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5907
5908 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005909 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005910 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5911 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5912 motionArgs.pointerCoords[0].getX() - 10);
5913
Prabir Pradhan678438e2023-04-13 19:32:51 +00005914 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005915 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005916 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005917}
5918
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005919/**
5920 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5921 * the device default right away. In the test scenario, we check both the default value,
5922 * and the action of enabling / disabling.
5923 */
5924TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005926 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5927 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005928 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005929
5930 // Set focused application.
5931 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005932 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005933
5934 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005936 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005937 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005938
5939 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005940 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005942 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005943
5944 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005945 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005946 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005947 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005948 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005950 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005951 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005952
5953 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005954 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005955 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005956 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005957
5958 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005959 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005960 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005961 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005962 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005963 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005964 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005965 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005966
5967 window->assertNoEvents();
5968}
5969
Gang Wange9087892020-01-07 12:17:14 -05005970TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005972 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5973 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005974
5975 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005976 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005977
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005979 setFocusedWindow(window);
5980
Harry Cutts33476232023-01-30 19:57:29 +00005981 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005982
Prabir Pradhan678438e2023-04-13 19:32:51 +00005983 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5984 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005985
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005986 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005987 ASSERT_NE(event, nullptr);
5988
5989 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5990 ASSERT_NE(verified, nullptr);
5991 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5992
5993 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5994 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5995 ASSERT_EQ(keyArgs.source, verified->source);
5996 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5997
5998 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5999
6000 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006001 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006002 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006003 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6004 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6005 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6006 ASSERT_EQ(0, verifiedKey.repeatCount);
6007}
6008
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006009TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006011 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6012 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006013
6014 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6015
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006016 ui::Transform transform;
6017 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6018
6019 gui::DisplayInfo displayInfo;
6020 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6021 displayInfo.transform = transform;
6022
Patrick Williamsd828f302023-04-28 17:52:08 -05006023 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006024
Prabir Pradhan678438e2023-04-13 19:32:51 +00006025 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006026 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6027 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006028 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006029
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006030 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006031 ASSERT_NE(event, nullptr);
6032
6033 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6034 ASSERT_NE(verified, nullptr);
6035 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6036
6037 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6038 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6039 EXPECT_EQ(motionArgs.source, verified->source);
6040 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6041
6042 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6043
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006044 const vec2 rawXY =
6045 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6046 motionArgs.pointerCoords[0].getXYValue());
6047 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6048 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006049 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006050 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006051 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006052 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6053 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6054}
6055
chaviw09c8d2d2020-08-24 15:48:26 -07006056/**
6057 * Ensure that separate calls to sign the same data are generating the same key.
6058 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6059 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6060 * tests.
6061 */
6062TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6063 KeyEvent event = getTestKeyEvent();
6064 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6065
6066 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6067 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6068 ASSERT_EQ(hmac1, hmac2);
6069}
6070
6071/**
6072 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6073 */
6074TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6075 KeyEvent event = getTestKeyEvent();
6076 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6077 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6078
6079 verifiedEvent.deviceId += 1;
6080 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6081
6082 verifiedEvent.source += 1;
6083 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6084
6085 verifiedEvent.eventTimeNanos += 1;
6086 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6087
6088 verifiedEvent.displayId += 1;
6089 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6090
6091 verifiedEvent.action += 1;
6092 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6093
6094 verifiedEvent.downTimeNanos += 1;
6095 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6096
6097 verifiedEvent.flags += 1;
6098 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6099
6100 verifiedEvent.keyCode += 1;
6101 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6102
6103 verifiedEvent.scanCode += 1;
6104 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6105
6106 verifiedEvent.metaState += 1;
6107 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6108
6109 verifiedEvent.repeatCount += 1;
6110 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6111}
6112
Vishnu Nair958da932020-08-21 17:12:37 -07006113TEST_F(InputDispatcherTest, SetFocusedWindow) {
6114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6115 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006116 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006117 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006118 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006119 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6120
6121 // Top window is also focusable but is not granted focus.
6122 windowTop->setFocusable(true);
6123 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006124 mDispatcher->onWindowInfosChanged(
6125 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006126 setFocusedWindow(windowSecond);
6127
6128 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006130 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006131
6132 // Focused window should receive event.
6133 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6134 windowTop->assertNoEvents();
6135}
6136
6137TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6138 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6139 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006140 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6142
6143 window->setFocusable(true);
6144 // Release channel for window is no longer valid.
6145 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006147 setFocusedWindow(window);
6148
6149 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006150 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006151
6152 // window channel is invalid, so it should not receive any input event.
6153 window->assertNoEvents();
6154}
6155
6156TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6158 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006159 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006160 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006161 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6162
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006163 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006164 setFocusedWindow(window);
6165
6166 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006167 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006168
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006169 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006170 window->assertNoEvents();
6171}
6172
6173TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6175 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006176 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006177 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006178 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006179 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6180
6181 windowTop->setFocusable(true);
6182 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006183 mDispatcher->onWindowInfosChanged(
6184 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006185 setFocusedWindow(windowTop);
6186 windowTop->consumeFocusEvent(true);
6187
Chavi Weingarten847e8512023-03-29 00:26:09 +00006188 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006189 mDispatcher->onWindowInfosChanged(
6190 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006191 windowSecond->consumeFocusEvent(true);
6192 windowTop->consumeFocusEvent(false);
6193
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006195 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006196
6197 // Focused window should receive event.
6198 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6199}
6200
Chavi Weingarten847e8512023-03-29 00:26:09 +00006201TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6203 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006204 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006205 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006206 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6208
6209 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006210 windowSecond->setFocusable(false);
6211 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006212 mDispatcher->onWindowInfosChanged(
6213 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006214 setFocusedWindow(windowTop);
6215 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006216
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006218 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006219
6220 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006221 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006222 windowSecond->assertNoEvents();
6223}
6224
6225TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6227 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006228 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006229 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006230 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6231 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006232 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6233
6234 window->setFocusable(true);
6235 previousFocusedWindow->setFocusable(true);
6236 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006237 mDispatcher->onWindowInfosChanged(
6238 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006239 setFocusedWindow(previousFocusedWindow);
6240 previousFocusedWindow->consumeFocusEvent(true);
6241
6242 // Requesting focus on invisible window takes focus from currently focused window.
6243 setFocusedWindow(window);
6244 previousFocusedWindow->consumeFocusEvent(false);
6245
6246 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006248 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6249 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006250
6251 // Window does not get focus event or key down.
6252 window->assertNoEvents();
6253
6254 // Window becomes visible.
6255 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006256 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006257
6258 // Window receives focus event.
6259 window->consumeFocusEvent(true);
6260 // Focused window receives key down.
6261 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6262}
6263
Vishnu Nair599f1412021-06-21 10:39:58 -07006264TEST_F(InputDispatcherTest, DisplayRemoved) {
6265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6266 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006267 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006268 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6269
6270 // window is granted focus.
6271 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006272 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006273 setFocusedWindow(window);
6274 window->consumeFocusEvent(true);
6275
6276 // When a display is removed window loses focus.
6277 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6278 window->consumeFocusEvent(false);
6279}
6280
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006281/**
6282 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6283 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6284 * of the 'slipperyEnterWindow'.
6285 *
6286 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6287 * a way so that the touched location is no longer covered by the top window.
6288 *
6289 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6290 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6291 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6292 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6293 * with ACTION_DOWN).
6294 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6295 * window moved itself away from the touched location and had Flag::SLIPPERY.
6296 *
6297 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6298 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6299 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6300 *
6301 * In this test, we ensure that the event received by the bottom window has
6302 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6303 */
6304TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006305 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006306 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006307
6308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6309 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6310
6311 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006312 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006313 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006314 // Make sure this one overlaps the bottom window
6315 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6316 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6317 // one. Windows with the same owner are not considered to be occluding each other.
6318 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6319
6320 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006322 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6323
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006324 mDispatcher->onWindowInfosChanged(
6325 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006326
6327 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006328 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6329 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6330 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006331 slipperyExitWindow->consumeMotionDown();
6332 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006333 mDispatcher->onWindowInfosChanged(
6334 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006335
Prabir Pradhan678438e2023-04-13 19:32:51 +00006336 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6337 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6338 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006339
6340 slipperyExitWindow->consumeMotionCancel();
6341
6342 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6343 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6344}
6345
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006346/**
6347 * Two windows, one on the left and another on the right. The left window is slippery. The right
6348 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6349 * touch moves from the left window into the right window, the gesture should continue to go to the
6350 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6351 * reproduces a crash.
6352 */
6353TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6354 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6355
6356 sp<FakeWindowHandle> leftSlipperyWindow =
6357 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6358 leftSlipperyWindow->setSlippery(true);
6359 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6360
6361 sp<FakeWindowHandle> rightDropTouchesWindow =
6362 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6363 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6364 rightDropTouchesWindow->setDropInput(true);
6365
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006366 mDispatcher->onWindowInfosChanged(
6367 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006368
6369 // Start touch in the left window
6370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6371 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6372 .build());
6373 leftSlipperyWindow->consumeMotionDown();
6374
6375 // And move it into the right window
6376 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6377 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6378 .build());
6379
6380 // Since the right window isn't eligible to receive input, touch does not slip.
6381 // The left window continues to receive the gesture.
6382 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6383 rightDropTouchesWindow->assertNoEvents();
6384}
6385
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006386/**
6387 * A single window is on screen first. Touch is injected into that window. Next, a second window
6388 * appears. Since the first window is slippery, touch will move from the first window to the second.
6389 */
6390TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6391 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6392 sp<FakeWindowHandle> originalWindow =
6393 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6394 originalWindow->setFrame(Rect(0, 0, 200, 200));
6395 originalWindow->setSlippery(true);
6396
6397 sp<FakeWindowHandle> appearingWindow =
6398 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6399 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6400
6401 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6402
6403 // Touch down on the original window
6404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6405 injectMotionEvent(*mDispatcher,
6406 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6407 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6408 .build()));
6409 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6410
6411 // Now, a new window appears. This could be, for example, a notification shade that appears
6412 // after user starts to drag down on the launcher window.
6413 mDispatcher->onWindowInfosChanged(
6414 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6416 injectMotionEvent(*mDispatcher,
6417 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6418 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6419 .build()));
6420 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6421 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6423 injectMotionEvent(*mDispatcher,
6424 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6425 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6426 .build()));
6427 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6428
6429 originalWindow->assertNoEvents();
6430 appearingWindow->assertNoEvents();
6431}
6432
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006433TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006434 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006435 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6436
6437 sp<FakeWindowHandle> leftWindow =
6438 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6439 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006440 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006441
6442 sp<FakeWindowHandle> rightSpy =
6443 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6444 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006445 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006446 rightSpy->setSpy(true);
6447 rightSpy->setTrustedOverlay(true);
6448
6449 sp<FakeWindowHandle> rightWindow =
6450 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6451 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006452 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006453
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006454 mDispatcher->onWindowInfosChanged(
6455 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006456
6457 // Touch in the left window
6458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6459 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6460 .build());
6461 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6462 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006463 ASSERT_NO_FATAL_FAILURE(
6464 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006465
6466 // Touch another finger over the right windows
6467 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6468 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6469 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6470 .build());
6471 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6472 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6473 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6474 mDispatcher->waitForIdle();
6475 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006476 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6477 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006478
6479 // Release finger over left window. The UP actions are not treated as device interaction.
6480 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6481 // is part of the UP action, we do not treat this as device interaction.
6482 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6483 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6484 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6485 .build());
6486 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6487 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6488 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6489 mDispatcher->waitForIdle();
6490 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6491
6492 // Move remaining finger
6493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6494 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6495 .build());
6496 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6497 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6498 mDispatcher->waitForIdle();
6499 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006500 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006501
6502 // Release all fingers
6503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6504 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6505 .build());
6506 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6507 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6508 mDispatcher->waitForIdle();
6509 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6510}
6511
6512TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6513 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6514
6515 sp<FakeWindowHandle> window =
6516 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6517 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006518 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006519
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006520 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006521 setFocusedWindow(window);
6522 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6523
6524 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6525 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6526 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006527 ASSERT_NO_FATAL_FAILURE(
6528 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006529
6530 // The UP actions are not treated as device interaction.
6531 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6532 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6533 mDispatcher->waitForIdle();
6534 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6535}
6536
Garfield Tan1c7bc862020-01-28 13:24:04 -08006537class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6538protected:
6539 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6540 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6541
Chris Yea209fde2020-07-22 13:54:51 -07006542 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006543 sp<FakeWindowHandle> mWindow;
6544
6545 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006546 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006547 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006548 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006549 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006550 ASSERT_EQ(OK, mDispatcher->start());
6551
6552 setUpWindow();
6553 }
6554
6555 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006556 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006557 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006558
Vishnu Nair47074b82020-08-14 11:54:47 -07006559 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006560 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006561 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006562 mWindow->consumeFocusEvent(true);
6563 }
6564
Chris Ye2ad95392020-09-01 13:44:44 -07006565 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006566 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006567 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006568 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006569 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006570
6571 // Window should receive key down event.
6572 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6573 }
6574
6575 void expectKeyRepeatOnce(int32_t repeatCount) {
6576 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006577 mWindow->consumeKeyEvent(
6578 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006579 }
6580
Chris Ye2ad95392020-09-01 13:44:44 -07006581 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006582 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006583 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006584 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006585 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006586
6587 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006588 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006589 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006590 }
6591};
6592
6593TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006594 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006595 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6596 expectKeyRepeatOnce(repeatCount);
6597 }
6598}
6599
6600TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006601 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006602 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6603 expectKeyRepeatOnce(repeatCount);
6604 }
Harry Cutts33476232023-01-30 19:57:29 +00006605 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006606 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006607 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6608 expectKeyRepeatOnce(repeatCount);
6609 }
6610}
6611
6612TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006613 sendAndConsumeKeyDown(/*deviceId=*/1);
6614 expectKeyRepeatOnce(/*repeatCount=*/1);
6615 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006616 mWindow->assertNoEvents();
6617}
6618
6619TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006620 sendAndConsumeKeyDown(/*deviceId=*/1);
6621 expectKeyRepeatOnce(/*repeatCount=*/1);
6622 sendAndConsumeKeyDown(/*deviceId=*/2);
6623 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006624 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006625 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006626 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006627 expectKeyRepeatOnce(/*repeatCount=*/2);
6628 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006629 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006630 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006631 mWindow->assertNoEvents();
6632}
6633
6634TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006635 sendAndConsumeKeyDown(/*deviceId=*/1);
6636 expectKeyRepeatOnce(/*repeatCount=*/1);
6637 sendAndConsumeKeyDown(/*deviceId=*/2);
6638 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006639 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006640 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006641 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006642 mWindow->assertNoEvents();
6643}
6644
liushenxiang42232912021-05-21 20:24:09 +08006645TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6646 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006647 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006648 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006649 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6650 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6651 mWindow->assertNoEvents();
6652}
6653
Garfield Tan1c7bc862020-01-28 13:24:04 -08006654TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006655 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006656 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006657 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006658 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006659 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6660 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6661 IdGenerator::getSource(repeatEvent->getId()));
6662 }
6663}
6664
6665TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006666 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006667 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006668
6669 std::unordered_set<int32_t> idSet;
6670 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006671 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006672 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6673 int32_t id = repeatEvent->getId();
6674 EXPECT_EQ(idSet.end(), idSet.find(id));
6675 idSet.insert(id);
6676 }
6677}
6678
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006679/* Test InputDispatcher for MultiDisplay */
6680class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6681public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006682 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006683 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006684
Chris Yea209fde2020-07-22 13:54:51 -07006685 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006686 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006687 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006688
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006689 // Set focus window for primary display, but focused display would be second one.
6690 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006691 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006692 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6693
Vishnu Nair958da932020-08-21 17:12:37 -07006694 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006695 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006696
Chris Yea209fde2020-07-22 13:54:51 -07006697 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006698 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006699 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006700 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006701 // Set focus display to second one.
6702 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6703 // Set focus window for second display.
6704 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006705 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006706 mDispatcher->onWindowInfosChanged(
6707 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006708 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006709 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006710 }
6711
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006712 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006713 InputDispatcherTest::TearDown();
6714
Chris Yea209fde2020-07-22 13:54:51 -07006715 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006716 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006717 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006718 windowInSecondary.clear();
6719 }
6720
6721protected:
Chris Yea209fde2020-07-22 13:54:51 -07006722 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006723 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006724 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006725 sp<FakeWindowHandle> windowInSecondary;
6726};
6727
6728TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6729 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006733 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006734 windowInSecondary->assertNoEvents();
6735
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006736 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006738 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006740 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006741 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006742}
6743
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006744TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006745 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006747 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006748 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006749 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006750 windowInSecondary->assertNoEvents();
6751
6752 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006754 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006755 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006756 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006757
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006758 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006759 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006760
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006761 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006762 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006763 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006764
6765 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006766 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006767 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006768 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006769 windowInSecondary->assertNoEvents();
6770}
6771
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006772// Test per-display input monitors for motion event.
6773TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006774 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006775 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006776 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006777 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006778
6779 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006781 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006783 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006784 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006785 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006786 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006787
6788 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006790 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006792 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006793 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006794 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006795 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006796
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006797 // Lift up the touch from the second display
6798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006799 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6801 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6802 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6803
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006804 // Test inject a non-pointer motion event.
6805 // If specific a display, it will dispatch to the focused window of particular display,
6806 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006808 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006810 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006811 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006812 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006813 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006814}
6815
6816// Test per-display input monitors for key event.
6817TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006818 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006819 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006820 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006821 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006822 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006823
6824 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006826 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006827 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006828 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006829 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006830 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006831}
6832
Vishnu Nair958da932020-08-21 17:12:37 -07006833TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6834 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006835 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006836 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006837 mDispatcher->onWindowInfosChanged(
6838 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6839 *windowInSecondary->getInfo()},
6840 {},
6841 0,
6842 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006843 setFocusedWindow(secondWindowInPrimary);
6844 windowInPrimary->consumeFocusEvent(false);
6845 secondWindowInPrimary->consumeFocusEvent(true);
6846
6847 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6849 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006850 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006851 windowInPrimary->assertNoEvents();
6852 windowInSecondary->assertNoEvents();
6853 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6854}
6855
Arthur Hungdfd528e2021-12-08 13:23:04 +00006856TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6857 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006858 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006859 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006860 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006861
6862 // Test touch down on primary display.
6863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006864 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6866 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6867 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6868
6869 // Test touch down on second display.
6870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006871 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6873 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6874 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6875
6876 // Trigger cancel touch.
6877 mDispatcher->cancelCurrentTouch();
6878 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6879 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6880 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6881 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6882
6883 // Test inject a move motion event, no window/monitor should receive the event.
6884 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006885 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006886 ADISPLAY_ID_DEFAULT, {110, 200}))
6887 << "Inject motion event should return InputEventInjectionResult::FAILED";
6888 windowInPrimary->assertNoEvents();
6889 monitorInPrimary.assertNoEvents();
6890
6891 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006892 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006893 SECOND_DISPLAY_ID, {110, 200}))
6894 << "Inject motion event should return InputEventInjectionResult::FAILED";
6895 windowInSecondary->assertNoEvents();
6896 monitorInSecondary.assertNoEvents();
6897}
6898
Jackal Guof9696682018-10-05 12:23:23 +08006899class InputFilterTest : public InputDispatcherTest {
6900protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006901 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6902 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006903 NotifyMotionArgs motionArgs;
6904
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006905 motionArgs =
6906 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006907 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006908 motionArgs =
6909 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006910 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006911 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006912 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006913 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006914 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006915 } else {
6916 mFakePolicy->assertFilterInputEventWasNotCalled();
6917 }
6918 }
6919
6920 void testNotifyKey(bool expectToBeFiltered) {
6921 NotifyKeyArgs keyArgs;
6922
6923 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006924 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006925 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006926 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006927 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006928
6929 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006930 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006931 } else {
6932 mFakePolicy->assertFilterInputEventWasNotCalled();
6933 }
6934 }
6935};
6936
6937// Test InputFilter for MotionEvent
6938TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6939 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006940 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6941 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006942
6943 // Enable InputFilter
6944 mDispatcher->setInputFilterEnabled(true);
6945 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006946 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6947 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006948
6949 // Disable InputFilter
6950 mDispatcher->setInputFilterEnabled(false);
6951 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006952 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6953 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006954}
6955
6956// Test InputFilter for KeyEvent
6957TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6958 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006959 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006960
6961 // Enable InputFilter
6962 mDispatcher->setInputFilterEnabled(true);
6963 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006964 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006965
6966 // Disable InputFilter
6967 mDispatcher->setInputFilterEnabled(false);
6968 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006969 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006970}
6971
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006972// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6973// logical display coordinate space.
6974TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6975 ui::Transform firstDisplayTransform;
6976 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6977 ui::Transform secondDisplayTransform;
6978 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6979
6980 std::vector<gui::DisplayInfo> displayInfos(2);
6981 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6982 displayInfos[0].transform = firstDisplayTransform;
6983 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6984 displayInfos[1].transform = secondDisplayTransform;
6985
Patrick Williamsd828f302023-04-28 17:52:08 -05006986 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006987
6988 // Enable InputFilter
6989 mDispatcher->setInputFilterEnabled(true);
6990
6991 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006992 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6993 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006994}
6995
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006996class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6997protected:
6998 virtual void SetUp() override {
6999 InputDispatcherTest::SetUp();
7000
7001 /**
7002 * We don't need to enable input filter to test the injected event policy, but we enabled it
7003 * here to make the tests more realistic, since this policy only matters when inputfilter is
7004 * on.
7005 */
7006 mDispatcher->setInputFilterEnabled(true);
7007
7008 std::shared_ptr<InputApplicationHandle> application =
7009 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007010 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7011 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007012
7013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7014 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007015 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007016 setFocusedWindow(mWindow);
7017 mWindow->consumeFocusEvent(true);
7018 }
7019
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007020 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7021 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007022 KeyEvent event;
7023
7024 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7025 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7026 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007027 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007028 const int32_t additionalPolicyFlags =
7029 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007031 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007032 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007033 policyFlags | additionalPolicyFlags));
7034
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007035 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007036 }
7037
7038 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7039 int32_t flags) {
7040 MotionEvent event;
7041 PointerProperties pointerProperties[1];
7042 PointerCoords pointerCoords[1];
7043 pointerProperties[0].clear();
7044 pointerProperties[0].id = 0;
7045 pointerCoords[0].clear();
7046 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7047 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7048
7049 ui::Transform identityTransform;
7050 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7051 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7052 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7053 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7054 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007055 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007056 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007057 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007058
7059 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007061 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007062 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007063 policyFlags | additionalPolicyFlags));
7064
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007065 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007066 }
7067
7068private:
7069 sp<FakeWindowHandle> mWindow;
7070};
7071
7072TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007073 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7074 // filter. Without it, the event will no different from a regularly injected event, and the
7075 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007076 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7077 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007078}
7079
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007080TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007081 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007082 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007083 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7084}
7085
7086TEST_F(InputFilterInjectionPolicyTest,
7087 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7088 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007089 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007090 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007091}
7092
7093TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007094 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7095 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007096}
7097
chaviwfd6d3512019-03-25 13:23:49 -07007098class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007099 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007100 InputDispatcherTest::SetUp();
7101
Chris Yea209fde2020-07-22 13:54:51 -07007102 std::shared_ptr<FakeApplicationHandle> application =
7103 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007104 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007105 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007106 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007107
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007108 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007109 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007110 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007111
7112 // Set focused application.
7113 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007114 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007115
7116 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007117 mDispatcher->onWindowInfosChanged(
7118 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007119 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007120 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007121 }
7122
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007123 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007124 InputDispatcherTest::TearDown();
7125
7126 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007127 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007128 }
7129
7130protected:
7131 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007132 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007133 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007134};
7135
7136// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7137// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7138// the onPointerDownOutsideFocus callback.
7139TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007141 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007142 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007144 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007145
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007146 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007147 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7148}
7149
7150// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7151// DOWN on the window that doesn't have focus. Ensure no window received the
7152// onPointerDownOutsideFocus callback.
7153TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007155 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7156 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007158 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007159
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007160 ASSERT_TRUE(mDispatcher->waitForIdle());
7161 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007162}
7163
7164// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7165// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7166TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007168 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007169 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007170 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007171
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007172 ASSERT_TRUE(mDispatcher->waitForIdle());
7173 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007174}
7175
7176// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7177// DOWN on the window that already has focus. Ensure no window received the
7178// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007179TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007181 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007182 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007184 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007185
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007186 ASSERT_TRUE(mDispatcher->waitForIdle());
7187 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007188}
7189
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007190// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7191// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7192TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7193 const MotionEvent event =
7194 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7195 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007196 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007197 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7198 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7201 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7202
7203 ASSERT_TRUE(mDispatcher->waitForIdle());
7204 mFakePolicy->assertOnPointerDownWasNotCalled();
7205 // Ensure that the unfocused window did not receive any FOCUS events.
7206 mUnfocusedWindow->assertNoEvents();
7207}
7208
chaviwaf87b3e2019-10-01 16:59:28 -07007209// These tests ensures we can send touch events to a single client when there are multiple input
7210// windows that point to the same client token.
7211class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7212 virtual void SetUp() override {
7213 InputDispatcherTest::SetUp();
7214
Chris Yea209fde2020-07-22 13:54:51 -07007215 std::shared_ptr<FakeApplicationHandle> application =
7216 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007217 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7218 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007219 mWindow1->setFrame(Rect(0, 0, 100, 100));
7220
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007221 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7222 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007223 mWindow2->setFrame(Rect(100, 100, 200, 200));
7224
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007225 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007226 }
7227
7228protected:
7229 sp<FakeWindowHandle> mWindow1;
7230 sp<FakeWindowHandle> mWindow2;
7231
7232 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007233 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007234 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7235 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007236 }
7237
7238 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7239 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007240 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007241 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007242
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007243 ASSERT_NE(nullptr, motionEvent)
7244 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007245
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007246 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007247 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007248
7249 for (size_t i = 0; i < points.size(); i++) {
7250 float expectedX = points[i].x;
7251 float expectedY = points[i].y;
7252
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007253 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007254 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007255 << ", got " << motionEvent->getX(i);
7256 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007257 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007258 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007259 }
7260 }
chaviw9eaa22c2020-07-01 16:21:27 -07007261
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007262 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007263 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007264 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7265 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007266
7267 // Always consume from window1 since it's the window that has the InputReceiver
7268 consumeMotionEvent(mWindow1, action, expectedPoints);
7269 }
chaviwaf87b3e2019-10-01 16:59:28 -07007270};
7271
7272TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7273 // Touch Window 1
7274 PointF touchedPoint = {10, 10};
7275 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007276 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007277
7278 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007279 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007280
7281 // Touch Window 2
7282 touchedPoint = {150, 150};
7283 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007284 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007285}
7286
chaviw9eaa22c2020-07-01 16:21:27 -07007287TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7288 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007289 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007290 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007291
7292 // Touch Window 1
7293 PointF touchedPoint = {10, 10};
7294 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007295 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007296 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007297 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007298
7299 // Touch Window 2
7300 touchedPoint = {150, 150};
7301 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007302 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7303 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007304
chaviw9eaa22c2020-07-01 16:21:27 -07007305 // Update the transform so rotation is set
7306 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007307 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007308 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7309 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007310}
7311
chaviw9eaa22c2020-07-01 16:21:27 -07007312TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007313 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007314 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007315
7316 // Touch Window 1
7317 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7318 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007319 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007320
7321 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007322 touchedPoints.push_back(PointF{150, 150});
7323 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007324 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007325
chaviw9eaa22c2020-07-01 16:21:27 -07007326 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007327 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007328 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007329
chaviw9eaa22c2020-07-01 16:21:27 -07007330 // Update the transform so rotation is set for Window 2
7331 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007332 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007333 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007334 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007335}
7336
chaviw9eaa22c2020-07-01 16:21:27 -07007337TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007338 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007339 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007340
7341 // Touch Window 1
7342 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7343 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007344 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007345
7346 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007347 touchedPoints.push_back(PointF{150, 150});
7348 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007349
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007350 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007351
7352 // Move both windows
7353 touchedPoints = {{20, 20}, {175, 175}};
7354 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7355 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7356
chaviw9eaa22c2020-07-01 16:21:27 -07007357 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007358
chaviw9eaa22c2020-07-01 16:21:27 -07007359 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007360 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007361 expectedPoints.pop_back();
7362
7363 // Touch Window 2
7364 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007365 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007366 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007367 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007368
7369 // Move both windows
7370 touchedPoints = {{20, 20}, {175, 175}};
7371 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7372 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7373
7374 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007375}
7376
7377TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7378 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007379 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007380
7381 // Touch Window 1
7382 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7383 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007384 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007385
7386 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007387 touchedPoints.push_back(PointF{150, 150});
7388 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007389
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007390 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007391
7392 // Move both windows
7393 touchedPoints = {{20, 20}, {175, 175}};
7394 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7395 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7396
chaviw9eaa22c2020-07-01 16:21:27 -07007397 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007398}
7399
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007400/**
7401 * When one of the windows is slippery, the touch should not slip into the other window with the
7402 * same input channel.
7403 */
7404TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7405 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007406 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007407
7408 // Touch down in window 1
7409 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7410 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7411 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7412
7413 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7414 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7415 // getting generated.
7416 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7417 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7418
7419 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7420}
7421
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007422/**
7423 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7424 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7425 * that the pointer is hovering over may have a different transform.
7426 */
7427TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007428 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007429
7430 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7432 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7433 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007434 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7435 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007436 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007437 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7438 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7439 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007440 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7441 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7442 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7443}
7444
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007445class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7446 virtual void SetUp() override {
7447 InputDispatcherTest::SetUp();
7448
Chris Yea209fde2020-07-22 13:54:51 -07007449 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007450 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007451 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7452 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007453 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007454 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007455 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007456
7457 // Set focused application.
7458 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7459
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007460 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007461 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007462 mWindow->consumeFocusEvent(true);
7463 }
7464
7465 virtual void TearDown() override {
7466 InputDispatcherTest::TearDown();
7467 mWindow.clear();
7468 }
7469
7470protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007471 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007472 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007473 sp<FakeWindowHandle> mWindow;
7474 static constexpr PointF WINDOW_LOCATION = {20, 20};
7475
7476 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007478 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007479 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007481 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007482 WINDOW_LOCATION));
7483 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007484
7485 sp<FakeWindowHandle> addSpyWindow() {
7486 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007487 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007488 spy->setTrustedOverlay(true);
7489 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007490 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007491 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007492 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007493 return spy;
7494 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007495};
7496
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007497// Send a tap and respond, which should not cause an ANR.
7498TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7499 tapOnWindow();
7500 mWindow->consumeMotionDown();
7501 mWindow->consumeMotionUp();
7502 ASSERT_TRUE(mDispatcher->waitForIdle());
7503 mFakePolicy->assertNotifyAnrWasNotCalled();
7504}
7505
7506// Send a regular key and respond, which should not cause an ANR.
7507TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007509 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7510 ASSERT_TRUE(mDispatcher->waitForIdle());
7511 mFakePolicy->assertNotifyAnrWasNotCalled();
7512}
7513
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007514TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7515 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007516 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007517 mWindow->consumeFocusEvent(false);
7518
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007519 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007520 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7521 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007522 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007524 // Key will not go to window because we have no focused window.
7525 // The 'no focused window' ANR timer should start instead.
7526
7527 // Now, the focused application goes away.
7528 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7529 // The key should get dropped and there should be no ANR.
7530
7531 ASSERT_TRUE(mDispatcher->waitForIdle());
7532 mFakePolicy->assertNotifyAnrWasNotCalled();
7533}
7534
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007535// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007536// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7537// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007538TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007540 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007541 WINDOW_LOCATION));
7542
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007543 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7544 ASSERT_TRUE(sequenceNum);
7545 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007546 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007547
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007548 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007549 mWindow->consumeMotionEvent(
7550 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007551 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007552 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007553}
7554
7555// Send a key to the app and have the app not respond right away.
7556TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7557 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007559 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7560 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007561 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007562 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007563 ASSERT_TRUE(mDispatcher->waitForIdle());
7564}
7565
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007566// We have a focused application, but no focused window
7567TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007568 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007569 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007570 mWindow->consumeFocusEvent(false);
7571
7572 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007574 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007575 WINDOW_LOCATION));
7576 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7577 mDispatcher->waitForIdle();
7578 mFakePolicy->assertNotifyAnrWasNotCalled();
7579
7580 // Once a focused event arrives, we get an ANR for this application
7581 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7582 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007583 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007584 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007585 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007586 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007587 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007588 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007589 ASSERT_TRUE(mDispatcher->waitForIdle());
7590}
7591
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007592/**
7593 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7594 * there will not be an ANR.
7595 */
7596TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7597 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007598 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007599 mWindow->consumeFocusEvent(false);
7600
7601 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007602 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7603 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007604 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7605 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7606
7607 // Define a valid key down event that is stale (too old).
7608 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007609 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007610 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007611
7612 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7613
7614 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007615 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007616 InputEventInjectionSync::WAIT_FOR_RESULT,
7617 INJECT_EVENT_TIMEOUT, policyFlags);
7618 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7619 << "Injection should fail because the event is stale";
7620
7621 ASSERT_TRUE(mDispatcher->waitForIdle());
7622 mFakePolicy->assertNotifyAnrWasNotCalled();
7623 mWindow->assertNoEvents();
7624}
7625
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007626// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007627// Make sure that we don't notify policy twice about the same ANR.
7628TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007629 const std::chrono::duration appTimeout = 400ms;
7630 mApplication->setDispatchingTimeout(appTimeout);
7631 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7632
Vishnu Nair47074b82020-08-14 11:54:47 -07007633 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007634 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007635 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007636
7637 // Once a focused event arrives, we get an ANR for this application
7638 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7639 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007640 const std::chrono::duration eventInjectionTimeout = 100ms;
7641 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007643 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007644 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7645 /*allowKeyRepeat=*/false);
7646 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7647 << "result=" << ftl::enum_string(result);
7648 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7649 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7650 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7651 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007652
Vishnu Naire4df8752022-09-08 09:17:55 -07007653 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007654 // ANR should not be raised again. It is up to policy to do that if it desires.
7655 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007656
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007657 // If we now get a focused window, the ANR should stop, but the policy handles that via
7658 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007659 ASSERT_TRUE(mDispatcher->waitForIdle());
7660}
7661
7662// We have a focused application, but no focused window
7663TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007664 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007665 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007666 mWindow->consumeFocusEvent(false);
7667
7668 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007669 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007670
Vishnu Naire4df8752022-09-08 09:17:55 -07007671 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7672 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007673
7674 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007675 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007676 ASSERT_TRUE(mDispatcher->waitForIdle());
7677 mWindow->assertNoEvents();
7678}
7679
7680/**
7681 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7682 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7683 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7684 * the ANR mechanism should still work.
7685 *
7686 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7687 * DOWN event, while not responding on the second one.
7688 */
7689TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7690 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007691 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007692 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7693 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7694 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007696
7697 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007698 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007699 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7700 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7701 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007702 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007703
7704 // We have now sent down and up. Let's consume first event and then ANR on the second.
7705 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7706 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007707 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007708}
7709
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007710// A spy window can receive an ANR
7711TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7712 sp<FakeWindowHandle> spy = addSpyWindow();
7713
7714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007716 WINDOW_LOCATION));
7717 mWindow->consumeMotionDown();
7718
7719 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7720 ASSERT_TRUE(sequenceNum);
7721 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007722 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007723
7724 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007725 spy->consumeMotionEvent(
7726 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007727 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007728 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007729}
7730
7731// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007732// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007733TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7734 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007735
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007737 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007738 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007740
7741 // Stuck on the ACTION_UP
7742 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007743 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007744
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007745 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007746 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007747 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7748 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007749
7750 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7751 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007752 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007753 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007754 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007755}
7756
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007757// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007758// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007759TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7760 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007761
7762 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007763 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7764 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007765
7766 mWindow->consumeMotionDown();
7767 // Stuck on the ACTION_UP
7768 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007769 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007770
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007771 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007772 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007773 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7774 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007775
7776 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7777 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007778 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007780 spy->assertNoEvents();
7781}
7782
7783TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007784 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007785
Prabir Pradhanfb549072023-10-05 19:17:36 +00007786 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007787
7788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007790 WINDOW_LOCATION));
7791
7792 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7793 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7794 ASSERT_TRUE(consumeSeq);
7795
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007796 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7797 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007798
7799 monitor.finishEvent(*consumeSeq);
7800 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7801
7802 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007803 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007804}
7805
7806// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7807// process events, you don't get an anr. When the window later becomes unresponsive again, you
7808// get an ANR again.
7809// 1. tap -> block on ACTION_UP -> receive ANR
7810// 2. consume all pending events (= queue becomes healthy again)
7811// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7812TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7813 tapOnWindow();
7814
7815 mWindow->consumeMotionDown();
7816 // Block on ACTION_UP
7817 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007818 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007819 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7820 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007821 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007822 mWindow->assertNoEvents();
7823
7824 tapOnWindow();
7825 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007826 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007827 mWindow->consumeMotionUp();
7828
7829 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007830 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007831 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007832 mWindow->assertNoEvents();
7833}
7834
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007835// If a connection remains unresponsive for a while, make sure policy is only notified once about
7836// it.
7837TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007840 WINDOW_LOCATION));
7841
7842 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007843 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007844 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007845 // 'notifyConnectionUnresponsive' should only be called once per connection
7846 mFakePolicy->assertNotifyAnrWasNotCalled();
7847 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007848 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007849 mWindow->consumeMotionEvent(
7850 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007851 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007852 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007853 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007854 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007855}
7856
7857/**
7858 * 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 -07007859 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007860 *
7861 * Warning!!!
7862 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7863 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007864 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007865 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7866 *
7867 * If that value changes, this test should also change.
7868 */
7869TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7870 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007871 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007872
7873 tapOnWindow();
7874 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7875 ASSERT_TRUE(downSequenceNum);
7876 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7877 ASSERT_TRUE(upSequenceNum);
7878 // Don't finish the events yet, and send a key
7879 // Injection will "succeed" because we will eventually give up and send the key to the focused
7880 // window even if motions are still being processed. But because the injection timeout is short,
7881 // we will receive INJECTION_TIMED_OUT as the result.
7882
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007883 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007884 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7885 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007886 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007887 // Key will not be sent to the window, yet, because the window is still processing events
7888 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007889 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7890 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7891 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7892 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007893
7894 std::this_thread::sleep_for(500ms);
7895 // if we wait long enough though, dispatcher will give up, and still send the key
7896 // to the focused window, even though we have not yet finished the motion event
7897 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7898 mWindow->finishEvent(*downSequenceNum);
7899 mWindow->finishEvent(*upSequenceNum);
7900}
7901
7902/**
7903 * If a window is processing a motion event, and then a key event comes in, the key event should
7904 * not go to the focused window until the motion is processed.
7905 * If then a new motion comes in, then the pending key event should be going to the currently
7906 * focused window right away.
7907 */
7908TEST_F(InputDispatcherSingleWindowAnr,
7909 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7910 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007911 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007912
7913 tapOnWindow();
7914 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7915 ASSERT_TRUE(downSequenceNum);
7916 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7917 ASSERT_TRUE(upSequenceNum);
7918 // Don't finish the events yet, and send a key
7919 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007921 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7922 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007923 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007924 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7925 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7926 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7927 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007928
7929 // Now tap down again. It should cause the pending key to go to the focused window right away.
7930 tapOnWindow();
7931 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7932 // the other events yet. We can finish events in any order.
7933 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7934 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7935 mWindow->consumeMotionDown();
7936 mWindow->consumeMotionUp();
7937 mWindow->assertNoEvents();
7938}
7939
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007940/**
7941 * Send an event to the app and have the app not respond right away.
7942 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7943 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7944 * At some point, the window becomes responsive again.
7945 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7946 */
7947TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7949 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7950 .build());
7951
7952 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7953 ASSERT_TRUE(sequenceNum);
7954 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7955 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7956
7957 mWindow->finishEvent(*sequenceNum);
7958 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7959 ASSERT_TRUE(mDispatcher->waitForIdle());
7960 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7961
7962 // Now that the window is responsive, let's continue the gesture.
7963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7964 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7965 .build());
7966
7967 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7968 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7969 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7970 .build());
7971
7972 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7973 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7974 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7975 .build());
7976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7977 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7978 .build());
7979 // We already canceled this pointer, so the window shouldn't get any new events.
7980 mWindow->assertNoEvents();
7981
7982 // Start another one.
7983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7984 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7985 .build());
7986 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7987}
7988
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007989class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7990 virtual void SetUp() override {
7991 InputDispatcherTest::SetUp();
7992
Chris Yea209fde2020-07-22 13:54:51 -07007993 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007994 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007995 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7996 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007997 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007998 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007999 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008000
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008001 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8002 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008003 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008004 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008005
8006 // Set focused application.
8007 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008008 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008009
8010 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008011 mDispatcher->onWindowInfosChanged(
8012 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008013 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008014 mFocusedWindow->consumeFocusEvent(true);
8015 }
8016
8017 virtual void TearDown() override {
8018 InputDispatcherTest::TearDown();
8019
8020 mUnfocusedWindow.clear();
8021 mFocusedWindow.clear();
8022 }
8023
8024protected:
Chris Yea209fde2020-07-22 13:54:51 -07008025 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026 sp<FakeWindowHandle> mUnfocusedWindow;
8027 sp<FakeWindowHandle> mFocusedWindow;
8028 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8029 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8030 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8031
8032 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8033
8034 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8035
8036private:
8037 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008039 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008040 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008042 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008043 location));
8044 }
8045};
8046
8047// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8048// should be ANR'd first.
8049TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008051 injectMotionEvent(*mDispatcher,
8052 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8053 AINPUT_SOURCE_TOUCHSCREEN)
8054 .pointer(PointerBuilder(0, ToolType::FINGER)
8055 .x(FOCUSED_WINDOW_LOCATION.x)
8056 .y(FOCUSED_WINDOW_LOCATION.y))
8057 .build()));
8058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8059 injectMotionEvent(*mDispatcher,
8060 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8061 AINPUT_SOURCE_TOUCHSCREEN)
8062 .pointer(PointerBuilder(0, ToolType::FINGER)
8063 .x(FOCUSED_WINDOW_LOCATION.x)
8064 .y(FOCUSED_WINDOW_LOCATION.y))
8065 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008066 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008067 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008068 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008069 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008070 // We consumed all events, so no ANR
8071 ASSERT_TRUE(mDispatcher->waitForIdle());
8072 mFakePolicy->assertNotifyAnrWasNotCalled();
8073
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008075 injectMotionEvent(*mDispatcher,
8076 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8077 AINPUT_SOURCE_TOUCHSCREEN)
8078 .pointer(PointerBuilder(0, ToolType::FINGER)
8079 .x(FOCUSED_WINDOW_LOCATION.x)
8080 .y(FOCUSED_WINDOW_LOCATION.y))
8081 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008082 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8083 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008084
8085 const std::chrono::duration timeout =
8086 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008087 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008088
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008089 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008090 mFocusedWindow->consumeMotionDown();
8091 // This cancel is generated because the connection was unresponsive
8092 mFocusedWindow->consumeMotionCancel();
8093 mFocusedWindow->assertNoEvents();
8094 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008095 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008096 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8097 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008098 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008099}
8100
8101// If we have 2 windows with identical timeouts that are both unresponsive,
8102// it doesn't matter which order they should have ANR.
8103// But we should receive ANR for both.
8104TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8105 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008106 mUnfocusedWindow->setDispatchingTimeout(
8107 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008108 mDispatcher->onWindowInfosChanged(
8109 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008110
8111 tapOnFocusedWindow();
8112 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008113 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008114 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8115 mFocusedWindow->getDispatchingTimeout(
8116 DISPATCHING_TIMEOUT)),
8117 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8118
8119 ASSERT_THAT(anrConnectionTokens,
8120 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8121 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008122
8123 ASSERT_TRUE(mDispatcher->waitForIdle());
8124 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008125
8126 mFocusedWindow->consumeMotionDown();
8127 mFocusedWindow->consumeMotionUp();
8128 mUnfocusedWindow->consumeMotionOutside();
8129
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008130 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8131 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008132
8133 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008134 ASSERT_THAT(responsiveTokens,
8135 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8136 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008137 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008138}
8139
8140// If a window is already not responding, the second tap on the same window should be ignored.
8141// We should also log an error to account for the dropped event (not tested here).
8142// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8143TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8144 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008145 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008146 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008147 // Receive the events, but don't respond
8148 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8149 ASSERT_TRUE(downEventSequenceNum);
8150 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8151 ASSERT_TRUE(upEventSequenceNum);
8152 const std::chrono::duration timeout =
8153 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008154 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008155
8156 // Tap once again
8157 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008158 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008160 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008161 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008162 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008163 FOCUSED_WINDOW_LOCATION));
8164 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8165 // valid touch target
8166 mUnfocusedWindow->assertNoEvents();
8167
8168 // Consume the first tap
8169 mFocusedWindow->finishEvent(*downEventSequenceNum);
8170 mFocusedWindow->finishEvent(*upEventSequenceNum);
8171 ASSERT_TRUE(mDispatcher->waitForIdle());
8172 // The second tap did not go to the focused window
8173 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008174 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008175 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8176 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008177 mFakePolicy->assertNotifyAnrWasNotCalled();
8178}
8179
8180// If you tap outside of all windows, there will not be ANR
8181TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008182 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008184 LOCATION_OUTSIDE_ALL_WINDOWS));
8185 ASSERT_TRUE(mDispatcher->waitForIdle());
8186 mFakePolicy->assertNotifyAnrWasNotCalled();
8187}
8188
8189// Since the focused window is paused, tapping on it should not produce any events
8190TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8191 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008192 mDispatcher->onWindowInfosChanged(
8193 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008195 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008196 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008197 FOCUSED_WINDOW_LOCATION));
8198
8199 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8200 ASSERT_TRUE(mDispatcher->waitForIdle());
8201 // Should not ANR because the window is paused, and touches shouldn't go to it
8202 mFakePolicy->assertNotifyAnrWasNotCalled();
8203
8204 mFocusedWindow->assertNoEvents();
8205 mUnfocusedWindow->assertNoEvents();
8206}
8207
8208/**
8209 * 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 -07008210 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008211 * If a different window becomes focused at this time, the key should go to that window instead.
8212 *
8213 * Warning!!!
8214 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8215 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008216 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008217 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8218 *
8219 * If that value changes, this test should also change.
8220 */
8221TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8222 // Set a long ANR timeout to prevent it from triggering
8223 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008224 mDispatcher->onWindowInfosChanged(
8225 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008226
8227 tapOnUnfocusedWindow();
8228 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8229 ASSERT_TRUE(downSequenceNum);
8230 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8231 ASSERT_TRUE(upSequenceNum);
8232 // Don't finish the events yet, and send a key
8233 // Injection will succeed because we will eventually give up and send the key to the focused
8234 // window even if motions are still being processed.
8235
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008236 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008237 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8238 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008240 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008241 // and the key remains pending, waiting for the touch events to be processed.
8242 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8243 // under the hood.
8244 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8245 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008246
8247 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008248 mFocusedWindow->setFocusable(false);
8249 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008250 mDispatcher->onWindowInfosChanged(
8251 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008252 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008253
8254 // Focus events should precede the key events
8255 mUnfocusedWindow->consumeFocusEvent(true);
8256 mFocusedWindow->consumeFocusEvent(false);
8257
8258 // Finish the tap events, which should unblock dispatcher
8259 mUnfocusedWindow->finishEvent(*downSequenceNum);
8260 mUnfocusedWindow->finishEvent(*upSequenceNum);
8261
8262 // Now that all queues are cleared and no backlog in the connections, the key event
8263 // can finally go to the newly focused "mUnfocusedWindow".
8264 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8265 mFocusedWindow->assertNoEvents();
8266 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008267 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008268}
8269
8270// When the touch stream is split across 2 windows, and one of them does not respond,
8271// then ANR should be raised and the touch should be canceled for the unresponsive window.
8272// The other window should not be affected by that.
8273TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8274 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008275 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8276 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8277 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008278 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008279 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280
8281 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008282 mDispatcher->notifyMotion(
8283 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8284 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008285
8286 const std::chrono::duration timeout =
8287 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008288 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008289
8290 mUnfocusedWindow->consumeMotionDown();
8291 mFocusedWindow->consumeMotionDown();
8292 // Focused window may or may not receive ACTION_MOVE
8293 // But it should definitely receive ACTION_CANCEL due to the ANR
8294 InputEvent* event;
8295 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8296 ASSERT_TRUE(moveOrCancelSequenceNum);
8297 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8298 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008299 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008300 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8301 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8302 mFocusedWindow->consumeMotionCancel();
8303 } else {
8304 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8305 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008306 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008307 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8308 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008309
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008310 mUnfocusedWindow->assertNoEvents();
8311 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008312 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008313}
8314
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008315/**
8316 * If we have no focused window, and a key comes in, we start the ANR timer.
8317 * The focused application should add a focused window before the timer runs out to prevent ANR.
8318 *
8319 * If the user touches another application during this time, the key should be dropped.
8320 * Next, if a new focused window comes in, without toggling the focused application,
8321 * then no ANR should occur.
8322 *
8323 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8324 * but in some cases the policy may not update the focused application.
8325 */
8326TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8327 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8328 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008329 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8331 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8332 mFocusedWindow->setFocusable(false);
8333
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008334 mDispatcher->onWindowInfosChanged(
8335 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008336 mFocusedWindow->consumeFocusEvent(false);
8337
8338 // Send a key. The ANR timer should start because there is no focused window.
8339 // 'focusedApplication' will get blamed if this timer completes.
8340 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008341 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008342 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8343 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008344 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008346
8347 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8348 // then the injected touches won't cause the focused event to get dropped.
8349 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8350 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8351 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8352 // For this test, it means that the key would get delivered to the window once it becomes
8353 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008354 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008355
8356 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8358 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8359 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008360
8361 // We do not consume the motion right away, because that would require dispatcher to first
8362 // process (== drop) the key event, and by that time, ANR will be raised.
8363 // Set the focused window first.
8364 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008365 mDispatcher->onWindowInfosChanged(
8366 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008367 setFocusedWindow(mFocusedWindow);
8368 mFocusedWindow->consumeFocusEvent(true);
8369 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8370 // to another application. This could be a bug / behaviour in the policy.
8371
8372 mUnfocusedWindow->consumeMotionDown();
8373
8374 ASSERT_TRUE(mDispatcher->waitForIdle());
8375 // Should not ANR because we actually have a focused window. It was just added too slowly.
8376 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8377}
8378
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008379// These tests ensure we cannot send touch events to a window that's positioned behind a window
8380// that has feature NO_INPUT_CHANNEL.
8381// Layout:
8382// Top (closest to user)
8383// mNoInputWindow (above all windows)
8384// mBottomWindow
8385// Bottom (furthest from user)
8386class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8387 virtual void SetUp() override {
8388 InputDispatcherTest::SetUp();
8389
8390 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008391 mNoInputWindow =
8392 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8393 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008394 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008395 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008396 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8397 // It's perfectly valid for this window to not have an associated input channel
8398
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008399 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8400 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008401 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008403 mDispatcher->onWindowInfosChanged(
8404 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008405 }
8406
8407protected:
8408 std::shared_ptr<FakeApplicationHandle> mApplication;
8409 sp<FakeWindowHandle> mNoInputWindow;
8410 sp<FakeWindowHandle> mBottomWindow;
8411};
8412
8413TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8414 PointF touchedPoint = {10, 10};
8415
Prabir Pradhan678438e2023-04-13 19:32:51 +00008416 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8417 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8418 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008419
8420 mNoInputWindow->assertNoEvents();
8421 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8422 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8423 // and therefore should prevent mBottomWindow from receiving touches
8424 mBottomWindow->assertNoEvents();
8425}
8426
8427/**
8428 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8429 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8430 */
8431TEST_F(InputDispatcherMultiWindowOcclusionTests,
8432 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008433 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8434 "Window with input channel and NO_INPUT_CHANNEL",
8435 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008436
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008437 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008438 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008439 mDispatcher->onWindowInfosChanged(
8440 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008441
8442 PointF touchedPoint = {10, 10};
8443
Prabir Pradhan678438e2023-04-13 19:32:51 +00008444 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8445 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8446 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008447
8448 mNoInputWindow->assertNoEvents();
8449 mBottomWindow->assertNoEvents();
8450}
8451
Vishnu Nair958da932020-08-21 17:12:37 -07008452class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8453protected:
8454 std::shared_ptr<FakeApplicationHandle> mApp;
8455 sp<FakeWindowHandle> mWindow;
8456 sp<FakeWindowHandle> mMirror;
8457
8458 virtual void SetUp() override {
8459 InputDispatcherTest::SetUp();
8460 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008461 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8462 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8463 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008464 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8465 mWindow->setFocusable(true);
8466 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008467 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008468 }
8469};
8470
8471TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8472 // Request focus on a mirrored window
8473 setFocusedWindow(mMirror);
8474
8475 // window gets focused
8476 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008478 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008479 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8480}
8481
8482// A focused & mirrored window remains focused only if the window and its mirror are both
8483// focusable.
8484TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8485 setFocusedWindow(mMirror);
8486
8487 // window gets focused
8488 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008490 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008491 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008493 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008494 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8495
8496 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008497 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008498
8499 // window loses focus since one of the windows associated with the token in not focusable
8500 mWindow->consumeFocusEvent(false);
8501
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008502 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008503 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008504 mWindow->assertNoEvents();
8505}
8506
8507// A focused & mirrored window remains focused until the window and its mirror both become
8508// invisible.
8509TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8510 setFocusedWindow(mMirror);
8511
8512 // window gets focused
8513 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008515 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008516 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008518 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008519 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8520
8521 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008522 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008523
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008525 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008526 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008528 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008529 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8530
8531 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008532 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008533
8534 // window loses focus only after all windows associated with the token become invisible.
8535 mWindow->consumeFocusEvent(false);
8536
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008537 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008538 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008539 mWindow->assertNoEvents();
8540}
8541
8542// A focused & mirrored window remains focused until both windows are removed.
8543TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8544 setFocusedWindow(mMirror);
8545
8546 // window gets focused
8547 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008549 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008550 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008552 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008553 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8554
8555 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008556 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008559 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008560 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008562 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008563 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8564
8565 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008566 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008567 mWindow->consumeFocusEvent(false);
8568
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008569 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008570 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008571 mWindow->assertNoEvents();
8572}
8573
8574// Focus request can be pending until one window becomes visible.
8575TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8576 // Request focus on an invisible mirror.
8577 mWindow->setVisible(false);
8578 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008579 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008580 setFocusedWindow(mMirror);
8581
8582 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008584 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8585 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008586
8587 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008588 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008589
8590 // window gets focused
8591 mWindow->consumeFocusEvent(true);
8592 // window gets the pending key event
8593 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8594}
Prabir Pradhan99987712020-11-10 18:43:05 -08008595
8596class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8597protected:
8598 std::shared_ptr<FakeApplicationHandle> mApp;
8599 sp<FakeWindowHandle> mWindow;
8600 sp<FakeWindowHandle> mSecondWindow;
8601
8602 void SetUp() override {
8603 InputDispatcherTest::SetUp();
8604 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008605 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008606 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008607 mSecondWindow =
8608 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008609 mSecondWindow->setFocusable(true);
8610
8611 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008612 mDispatcher->onWindowInfosChanged(
8613 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008614
8615 setFocusedWindow(mWindow);
8616 mWindow->consumeFocusEvent(true);
8617 }
8618
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008619 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008620 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008621 }
8622
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008623 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8624 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008625 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008626 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8627 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008628 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008629 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008630 }
8631};
8632
8633TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8634 // Ensure that capture cannot be obtained for unfocused windows.
8635 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8636 mFakePolicy->assertSetPointerCaptureNotCalled();
8637 mSecondWindow->assertNoEvents();
8638
8639 // Ensure that capture can be enabled from the focus window.
8640 requestAndVerifyPointerCapture(mWindow, true);
8641
8642 // Ensure that capture cannot be disabled from a window that does not have capture.
8643 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8644 mFakePolicy->assertSetPointerCaptureNotCalled();
8645
8646 // Ensure that capture can be disabled from the window with capture.
8647 requestAndVerifyPointerCapture(mWindow, false);
8648}
8649
8650TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008651 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008652
8653 setFocusedWindow(mSecondWindow);
8654
8655 // Ensure that the capture disabled event was sent first.
8656 mWindow->consumeCaptureEvent(false);
8657 mWindow->consumeFocusEvent(false);
8658 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008659 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008660
8661 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008662 notifyPointerCaptureChanged({});
8663 notifyPointerCaptureChanged(request);
8664 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008665 mWindow->assertNoEvents();
8666 mSecondWindow->assertNoEvents();
8667 mFakePolicy->assertSetPointerCaptureNotCalled();
8668}
8669
8670TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008671 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008672
8673 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008674 notifyPointerCaptureChanged({});
8675 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008676
8677 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008678 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008679 mWindow->consumeCaptureEvent(false);
8680 mWindow->assertNoEvents();
8681}
8682
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008683TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8684 requestAndVerifyPointerCapture(mWindow, true);
8685
8686 // The first window loses focus.
8687 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008688 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008689 mWindow->consumeCaptureEvent(false);
8690
8691 // Request Pointer Capture from the second window before the notification from InputReader
8692 // arrives.
8693 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008694 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008695
8696 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008697 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008698
8699 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008700 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008701
8702 mSecondWindow->consumeFocusEvent(true);
8703 mSecondWindow->consumeCaptureEvent(true);
8704}
8705
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008706TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8707 // App repeatedly enables and disables capture.
8708 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8709 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8710 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8711 mFakePolicy->assertSetPointerCaptureCalled(false);
8712 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8713 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8714
8715 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8716 // first request is now stale, this should do nothing.
8717 notifyPointerCaptureChanged(firstRequest);
8718 mWindow->assertNoEvents();
8719
8720 // InputReader notifies that the second request was enabled.
8721 notifyPointerCaptureChanged(secondRequest);
8722 mWindow->consumeCaptureEvent(true);
8723}
8724
Prabir Pradhan7092e262022-05-03 16:51:09 +00008725TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8726 requestAndVerifyPointerCapture(mWindow, true);
8727
8728 // App toggles pointer capture off and on.
8729 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8730 mFakePolicy->assertSetPointerCaptureCalled(false);
8731
8732 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8733 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8734
8735 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8736 // preceding "disable" request.
8737 notifyPointerCaptureChanged(enableRequest);
8738
8739 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8740 // any notifications.
8741 mWindow->assertNoEvents();
8742}
8743
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008744/**
8745 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8746 * mouse movements don't affect the previous mouse hovering state.
8747 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8748 * HOVER_MOVE events).
8749 */
8750TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8751 // Mouse hover on the window
8752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8753 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8754 .build());
8755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8756 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8757 .build());
8758
8759 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8760 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8761
8762 // Start pointer capture
8763 requestAndVerifyPointerCapture(mWindow, true);
8764
8765 // Send some relative mouse movements and receive them in the window.
8766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8767 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8768 .build());
8769 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8770 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8771
8772 // Stop pointer capture
8773 requestAndVerifyPointerCapture(mWindow, false);
8774
8775 // Continue hovering on the window
8776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8777 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8778 .build());
8779 mWindow->consumeMotionEvent(
8780 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8781
8782 mWindow->assertNoEvents();
8783}
8784
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008785class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8786protected:
8787 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008788
8789 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8790 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8791
8792 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8793 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8794
8795 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8796 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8797 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8798 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8799 MAXIMUM_OBSCURING_OPACITY);
8800
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008801 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8802 static constexpr gui::Uid APP_B_UID{10002};
8803 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008804
8805 sp<FakeWindowHandle> mTouchWindow;
8806
8807 virtual void SetUp() override {
8808 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008809 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008810 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8811 }
8812
8813 virtual void TearDown() override {
8814 InputDispatcherTest::TearDown();
8815 mTouchWindow.clear();
8816 }
8817
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008818 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008819 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008820 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008821 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008822 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008823 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008824 return window;
8825 }
8826
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008827 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008828 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8829 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008830 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008831 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008832 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008833 return window;
8834 }
8835
8836 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008837 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8838 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8839 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008840 }
8841};
8842
8843TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008844 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008845 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008846 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008847
8848 touch();
8849
8850 mTouchWindow->assertNoEvents();
8851}
8852
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008853TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008854 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8855 const sp<FakeWindowHandle>& w =
8856 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008857 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008858
8859 touch();
8860
8861 mTouchWindow->assertNoEvents();
8862}
8863
8864TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008865 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8866 const sp<FakeWindowHandle>& w =
8867 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008868 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008869
8870 touch();
8871
8872 w->assertNoEvents();
8873}
8874
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008875TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008876 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008877 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008878
8879 touch();
8880
8881 mTouchWindow->consumeAnyMotionDown();
8882}
8883
8884TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008885 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008886 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008887 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008888 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008889
8890 touch({PointF{100, 100}});
8891
8892 mTouchWindow->consumeAnyMotionDown();
8893}
8894
8895TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008896 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008897 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008898 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008899
8900 touch();
8901
8902 mTouchWindow->consumeAnyMotionDown();
8903}
8904
8905TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8906 const sp<FakeWindowHandle>& w =
8907 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008908 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008909
8910 touch();
8911
8912 mTouchWindow->consumeAnyMotionDown();
8913}
8914
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008915TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8916 const sp<FakeWindowHandle>& w =
8917 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008918 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008919
8920 touch();
8921
8922 w->assertNoEvents();
8923}
8924
8925/**
8926 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8927 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8928 * window, the occluding window will still receive ACTION_OUTSIDE event.
8929 */
8930TEST_F(InputDispatcherUntrustedTouchesTest,
8931 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8932 const sp<FakeWindowHandle>& w =
8933 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008934 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008935 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008936
8937 touch();
8938
8939 w->consumeMotionOutside();
8940}
8941
8942TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8943 const sp<FakeWindowHandle>& w =
8944 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008945 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008946 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008947
8948 touch();
8949
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008950 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008951}
8952
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008953TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008954 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008955 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8956 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008957 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008958
8959 touch();
8960
8961 mTouchWindow->consumeAnyMotionDown();
8962}
8963
8964TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8965 const sp<FakeWindowHandle>& w =
8966 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8967 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008968 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008969
8970 touch();
8971
8972 mTouchWindow->consumeAnyMotionDown();
8973}
8974
8975TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008976 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008977 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8978 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008979 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008980
8981 touch();
8982
8983 mTouchWindow->assertNoEvents();
8984}
8985
8986TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8987 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8988 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008989 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8990 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008991 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008992 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8993 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008994 mDispatcher->onWindowInfosChanged(
8995 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008996
8997 touch();
8998
8999 mTouchWindow->assertNoEvents();
9000}
9001
9002TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9003 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9004 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009005 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9006 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009007 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009008 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9009 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009010 mDispatcher->onWindowInfosChanged(
9011 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009012
9013 touch();
9014
9015 mTouchWindow->consumeAnyMotionDown();
9016}
9017
9018TEST_F(InputDispatcherUntrustedTouchesTest,
9019 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9020 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009021 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9022 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009023 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009024 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9025 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009026 mDispatcher->onWindowInfosChanged(
9027 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009028
9029 touch();
9030
9031 mTouchWindow->consumeAnyMotionDown();
9032}
9033
9034TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9035 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009036 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9037 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009038 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009039 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9040 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009041 mDispatcher->onWindowInfosChanged(
9042 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009043
9044 touch();
9045
9046 mTouchWindow->assertNoEvents();
9047}
9048
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009049TEST_F(InputDispatcherUntrustedTouchesTest,
9050 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9051 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009052 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9053 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009054 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009055 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9056 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009057 mDispatcher->onWindowInfosChanged(
9058 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009059
9060 touch();
9061
9062 mTouchWindow->assertNoEvents();
9063}
9064
9065TEST_F(InputDispatcherUntrustedTouchesTest,
9066 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9067 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009068 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9069 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009070 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009071 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9072 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009073 mDispatcher->onWindowInfosChanged(
9074 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009075
9076 touch();
9077
9078 mTouchWindow->consumeAnyMotionDown();
9079}
9080
9081TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9082 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009083 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9084 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009085 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009086
9087 touch();
9088
9089 mTouchWindow->consumeAnyMotionDown();
9090}
9091
9092TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9093 const sp<FakeWindowHandle>& w =
9094 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009095 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009096
9097 touch();
9098
9099 mTouchWindow->consumeAnyMotionDown();
9100}
9101
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009102TEST_F(InputDispatcherUntrustedTouchesTest,
9103 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9104 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9105 const sp<FakeWindowHandle>& w =
9106 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009107 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009108
9109 touch();
9110
9111 mTouchWindow->assertNoEvents();
9112}
9113
9114TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9115 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9116 const sp<FakeWindowHandle>& w =
9117 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009118 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009119
9120 touch();
9121
9122 mTouchWindow->consumeAnyMotionDown();
9123}
9124
9125TEST_F(InputDispatcherUntrustedTouchesTest,
9126 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9127 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9128 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009129 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9130 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009131 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009132
9133 touch();
9134
9135 mTouchWindow->consumeAnyMotionDown();
9136}
9137
9138TEST_F(InputDispatcherUntrustedTouchesTest,
9139 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9140 const sp<FakeWindowHandle>& w1 =
9141 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9142 OPACITY_BELOW_THRESHOLD);
9143 const sp<FakeWindowHandle>& w2 =
9144 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9145 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009146 mDispatcher->onWindowInfosChanged(
9147 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009148
9149 touch();
9150
9151 mTouchWindow->assertNoEvents();
9152}
9153
9154/**
9155 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9156 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9157 * (which alone would result in allowing touches) does not affect the blocking behavior.
9158 */
9159TEST_F(InputDispatcherUntrustedTouchesTest,
9160 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9161 const sp<FakeWindowHandle>& wB =
9162 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9163 OPACITY_BELOW_THRESHOLD);
9164 const sp<FakeWindowHandle>& wC =
9165 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9166 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009167 mDispatcher->onWindowInfosChanged(
9168 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009169
9170 touch();
9171
9172 mTouchWindow->assertNoEvents();
9173}
9174
9175/**
9176 * This test is testing that a window from a different UID but with same application token doesn't
9177 * block the touch. Apps can share the application token for close UI collaboration for example.
9178 */
9179TEST_F(InputDispatcherUntrustedTouchesTest,
9180 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9181 const sp<FakeWindowHandle>& w =
9182 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9183 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009184 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009185
9186 touch();
9187
9188 mTouchWindow->consumeAnyMotionDown();
9189}
9190
arthurhungb89ccb02020-12-30 16:19:01 +08009191class InputDispatcherDragTests : public InputDispatcherTest {
9192protected:
9193 std::shared_ptr<FakeApplicationHandle> mApp;
9194 sp<FakeWindowHandle> mWindow;
9195 sp<FakeWindowHandle> mSecondWindow;
9196 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009197 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009198 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9199 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009200
9201 void SetUp() override {
9202 InputDispatcherTest::SetUp();
9203 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009204 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009205 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009206
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009207 mSecondWindow =
9208 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009209 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009210
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009211 mSpyWindow =
9212 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009213 mSpyWindow->setSpy(true);
9214 mSpyWindow->setTrustedOverlay(true);
9215 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9216
arthurhungb89ccb02020-12-30 16:19:01 +08009217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009218 mDispatcher->onWindowInfosChanged(
9219 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9220 {},
9221 0,
9222 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009223 }
9224
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009225 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9226 switch (fromSource) {
9227 case AINPUT_SOURCE_TOUCHSCREEN:
9228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009229 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009230 ADISPLAY_ID_DEFAULT, {50, 50}))
9231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9232 break;
9233 case AINPUT_SOURCE_STYLUS:
9234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009235 injectMotionEvent(*mDispatcher,
9236 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9237 AINPUT_SOURCE_STYLUS)
9238 .buttonState(
9239 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9240 .pointer(PointerBuilder(0, ToolType::STYLUS)
9241 .x(50)
9242 .y(50))
9243 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009244 break;
9245 case AINPUT_SOURCE_MOUSE:
9246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009247 injectMotionEvent(*mDispatcher,
9248 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9249 AINPUT_SOURCE_MOUSE)
9250 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9251 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9252 ToolType::MOUSE)
9253 .x(50)
9254 .y(50))
9255 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009256 break;
9257 default:
9258 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9259 }
arthurhungb89ccb02020-12-30 16:19:01 +08009260
9261 // Window should receive motion event.
9262 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009263 // Spy window should also receive motion event
9264 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009265 }
9266
9267 // Start performing drag, we will create a drag window and transfer touch to it.
9268 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9269 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009270 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009271 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009272 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009273 }
arthurhungb89ccb02020-12-30 16:19:01 +08009274
9275 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009276 mDragWindow =
9277 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009278 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009279 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9280 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9281 {},
9282 0,
9283 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009284
9285 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009286 bool transferred =
9287 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009288 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009289 if (transferred) {
9290 mWindow->consumeMotionCancel();
9291 mDragWindow->consumeMotionDown();
9292 }
9293 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009294 }
9295};
9296
9297TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009298 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009299
9300 // Move on window.
9301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009302 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009303 ADISPLAY_ID_DEFAULT, {50, 50}))
9304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9305 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9306 mWindow->consumeDragEvent(false, 50, 50);
9307 mSecondWindow->assertNoEvents();
9308
9309 // Move to another window.
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009312 ADISPLAY_ID_DEFAULT, {150, 50}))
9313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9314 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9315 mWindow->consumeDragEvent(true, 150, 50);
9316 mSecondWindow->consumeDragEvent(false, 50, 50);
9317
9318 // Move back to original window.
9319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009320 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009321 ADISPLAY_ID_DEFAULT, {50, 50}))
9322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9323 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9324 mWindow->consumeDragEvent(false, 50, 50);
9325 mSecondWindow->consumeDragEvent(true, -50, 50);
9326
9327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009328 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9329 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9331 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9332 mWindow->assertNoEvents();
9333 mSecondWindow->assertNoEvents();
9334}
9335
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009336TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009337 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009338
9339 // No cancel event after drag start
9340 mSpyWindow->assertNoEvents();
9341
9342 const MotionEvent secondFingerDownEvent =
9343 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9344 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009345 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9346 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009347 .build();
9348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009349 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009350 InputEventInjectionSync::WAIT_FOR_RESULT))
9351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9352
9353 // Receives cancel for first pointer after next pointer down
9354 mSpyWindow->consumeMotionCancel();
9355 mSpyWindow->consumeMotionDown();
9356
9357 mSpyWindow->assertNoEvents();
9358}
9359
arthurhungf452d0b2021-01-06 00:19:52 +08009360TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009361 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009362
9363 // Move on window.
9364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009365 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009366 ADISPLAY_ID_DEFAULT, {50, 50}))
9367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9368 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9369 mWindow->consumeDragEvent(false, 50, 50);
9370 mSecondWindow->assertNoEvents();
9371
9372 // Move to another window.
9373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009374 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009375 ADISPLAY_ID_DEFAULT, {150, 50}))
9376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9377 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9378 mWindow->consumeDragEvent(true, 150, 50);
9379 mSecondWindow->consumeDragEvent(false, 50, 50);
9380
9381 // drop to another window.
9382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009383 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009384 {150, 50}))
9385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9386 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009387 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009388 mWindow->assertNoEvents();
9389 mSecondWindow->assertNoEvents();
9390}
9391
arthurhung6d4bed92021-03-17 11:59:33 +08009392TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009393 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009394
9395 // Move on window and keep button pressed.
9396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009397 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009398 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9399 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009400 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009401 .build()))
9402 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9403 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9404 mWindow->consumeDragEvent(false, 50, 50);
9405 mSecondWindow->assertNoEvents();
9406
9407 // Move to another window and release button, expect to drop item.
9408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009409 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009410 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9411 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009413 .build()))
9414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9415 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9416 mWindow->assertNoEvents();
9417 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009418 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009419
9420 // nothing to the window.
9421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009422 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009423 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9424 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009425 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009426 .build()))
9427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9428 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9429 mWindow->assertNoEvents();
9430 mSecondWindow->assertNoEvents();
9431}
9432
Arthur Hung54745652022-04-20 07:17:41 +00009433TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009434 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009435
9436 // Set second window invisible.
9437 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009438 mDispatcher->onWindowInfosChanged(
9439 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009440
9441 // Move on window.
9442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009443 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009444 ADISPLAY_ID_DEFAULT, {50, 50}))
9445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9446 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9447 mWindow->consumeDragEvent(false, 50, 50);
9448 mSecondWindow->assertNoEvents();
9449
9450 // Move to another window.
9451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009452 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009453 ADISPLAY_ID_DEFAULT, {150, 50}))
9454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9455 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9456 mWindow->consumeDragEvent(true, 150, 50);
9457 mSecondWindow->assertNoEvents();
9458
9459 // drop to another window.
9460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009461 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009462 {150, 50}))
9463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9464 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009465 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009466 mWindow->assertNoEvents();
9467 mSecondWindow->assertNoEvents();
9468}
9469
Arthur Hung54745652022-04-20 07:17:41 +00009470TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009471 // Ensure window could track pointerIds if it didn't support split touch.
9472 mWindow->setPreventSplitting(true);
9473
Arthur Hung54745652022-04-20 07:17:41 +00009474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009475 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009476 {50, 50}))
9477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9478 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9479
9480 const MotionEvent secondFingerDownEvent =
9481 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9482 .displayId(ADISPLAY_ID_DEFAULT)
9483 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009484 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9485 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009486 .build();
9487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009488 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009489 InputEventInjectionSync::WAIT_FOR_RESULT))
9490 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009491 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009492
9493 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009494 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009495}
9496
9497TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9498 // First down on second window.
9499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009500 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009501 {150, 50}))
9502 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9503
9504 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9505
9506 // Second down on first window.
9507 const MotionEvent secondFingerDownEvent =
9508 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9509 .displayId(ADISPLAY_ID_DEFAULT)
9510 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009511 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9512 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009513 .build();
9514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009515 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009516 InputEventInjectionSync::WAIT_FOR_RESULT))
9517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9518 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9519
9520 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009521 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009522
9523 // Move on window.
9524 const MotionEvent secondFingerMoveEvent =
9525 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9526 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009527 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9528 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009529 .build();
9530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009531 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009532 InputEventInjectionSync::WAIT_FOR_RESULT));
9533 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9534 mWindow->consumeDragEvent(false, 50, 50);
9535 mSecondWindow->consumeMotionMove();
9536
9537 // Release the drag pointer should perform drop.
9538 const MotionEvent secondFingerUpEvent =
9539 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9540 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009541 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9542 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009543 .build();
9544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009545 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009546 InputEventInjectionSync::WAIT_FOR_RESULT));
9547 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009548 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009549 mWindow->assertNoEvents();
9550 mSecondWindow->consumeMotionMove();
9551}
9552
Arthur Hung3915c1f2022-05-31 07:17:17 +00009553TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009554 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009555
9556 // Update window of second display.
9557 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009558 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009559 mDispatcher->onWindowInfosChanged(
9560 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9561 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9562 {},
9563 0,
9564 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009565
9566 // Let second display has a touch state.
9567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009568 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009569 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9570 AINPUT_SOURCE_TOUCHSCREEN)
9571 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009572 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009573 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009574 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009575 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009576 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009577 mDispatcher->onWindowInfosChanged(
9578 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9579 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9580 {},
9581 0,
9582 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009583
9584 // Move on window.
9585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009586 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009587 ADISPLAY_ID_DEFAULT, {50, 50}))
9588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9589 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9590 mWindow->consumeDragEvent(false, 50, 50);
9591 mSecondWindow->assertNoEvents();
9592
9593 // Move to another window.
9594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009595 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009596 ADISPLAY_ID_DEFAULT, {150, 50}))
9597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9598 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9599 mWindow->consumeDragEvent(true, 150, 50);
9600 mSecondWindow->consumeDragEvent(false, 50, 50);
9601
9602 // drop to another window.
9603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009604 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009605 {150, 50}))
9606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9607 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009608 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009609 mWindow->assertNoEvents();
9610 mSecondWindow->assertNoEvents();
9611}
9612
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009613TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9614 startDrag(true, AINPUT_SOURCE_MOUSE);
9615 // Move on window.
9616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009617 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009618 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9619 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009620 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009621 .x(50)
9622 .y(50))
9623 .build()))
9624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9625 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9626 mWindow->consumeDragEvent(false, 50, 50);
9627 mSecondWindow->assertNoEvents();
9628
9629 // Move to another window.
9630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009631 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009632 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9633 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009634 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009635 .x(150)
9636 .y(50))
9637 .build()))
9638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9639 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9640 mWindow->consumeDragEvent(true, 150, 50);
9641 mSecondWindow->consumeDragEvent(false, 50, 50);
9642
9643 // drop to another window.
9644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009645 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009646 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9647 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009648 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009649 .x(150)
9650 .y(50))
9651 .build()))
9652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9653 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009654 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009655 mWindow->assertNoEvents();
9656 mSecondWindow->assertNoEvents();
9657}
9658
Linnan Li5af92f92023-07-14 14:36:22 +08009659/**
9660 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9661 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9662 */
9663TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9664 // Down on second window
9665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9666 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9667 {150, 50}))
9668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9669
9670 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9671 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9672
9673 // Down on first window
9674 const MotionEvent secondFingerDownEvent =
9675 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9676 .displayId(ADISPLAY_ID_DEFAULT)
9677 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9678 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9679 .build();
9680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9681 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9682 InputEventInjectionSync::WAIT_FOR_RESULT))
9683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9684 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9685 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9686 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9687
9688 // Start drag on first window
9689 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9690
9691 // Trigger cancel
9692 mDispatcher->cancelCurrentTouch();
9693 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9694 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9695 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9696
9697 ASSERT_TRUE(mDispatcher->waitForIdle());
9698 // The D&D finished with nullptr
9699 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9700
9701 // Remove drag window
9702 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9703
9704 // Inject a simple gesture, ensure dispatcher not crashed
9705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9706 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9707 PointF{50, 50}))
9708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9709 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9710
9711 const MotionEvent moveEvent =
9712 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9713 .displayId(ADISPLAY_ID_DEFAULT)
9714 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9715 .build();
9716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9717 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9718 InputEventInjectionSync::WAIT_FOR_RESULT))
9719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9720 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9721
9722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9723 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9724 {50, 50}))
9725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9726 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9727}
9728
Vishnu Nair062a8672021-09-03 16:07:44 -07009729class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9730
9731TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9734 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009735 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009736 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9737 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009739 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009740 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009741
9742 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009743 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009744 window->assertNoEvents();
9745
Prabir Pradhan678438e2023-04-13 19:32:51 +00009746 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9747 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009748 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9749 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009750 window->assertNoEvents();
9751
9752 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009753 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009754 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009755
Prabir Pradhan678438e2023-04-13 19:32:51 +00009756 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009757 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9758
Prabir Pradhan678438e2023-04-13 19:32:51 +00009759 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9760 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009761 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9762 window->assertNoEvents();
9763}
9764
9765TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9766 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9767 std::make_shared<FakeApplicationHandle>();
9768 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009769 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9770 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009771 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009772 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009773 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009775 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9776 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009777 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009778 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009779 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9780 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009781 mDispatcher->onWindowInfosChanged(
9782 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009783 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009784 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009785
9786 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009787 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009788 window->assertNoEvents();
9789
Prabir Pradhan678438e2023-04-13 19:32:51 +00009790 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9791 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009792 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9793 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009794 window->assertNoEvents();
9795
9796 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009797 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009798 mDispatcher->onWindowInfosChanged(
9799 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009800
Prabir Pradhan678438e2023-04-13 19:32:51 +00009801 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009802 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9803
Prabir Pradhan678438e2023-04-13 19:32:51 +00009804 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9805 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009806 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9807 window->assertNoEvents();
9808}
9809
9810TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9811 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9812 std::make_shared<FakeApplicationHandle>();
9813 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009814 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9815 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009816 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009817 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009818 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9821 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009822 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009823 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009824 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9825 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009826 mDispatcher->onWindowInfosChanged(
9827 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009828 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009829 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009830
9831 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009832 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009833 window->assertNoEvents();
9834
Prabir Pradhan678438e2023-04-13 19:32:51 +00009835 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9836 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009837 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9838 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009839 window->assertNoEvents();
9840
9841 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009842 mDispatcher->onWindowInfosChanged(
9843 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009844
Prabir Pradhan678438e2023-04-13 19:32:51 +00009845 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009846 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9847
Prabir Pradhan678438e2023-04-13 19:32:51 +00009848 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9849 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009850 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9851 window->assertNoEvents();
9852}
9853
Antonio Kantekf16f2832021-09-28 04:39:20 +00009854class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9855protected:
9856 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009857 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009858 sp<FakeWindowHandle> mWindow;
9859 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009860 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009861
9862 void SetUp() override {
9863 InputDispatcherTest::SetUp();
9864
9865 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009866 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009867 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009868 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009869 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009870 mSecondWindow =
9871 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009872 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009873 mThirdWindow =
9874 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9875 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9876 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009877
9878 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009879 mDispatcher->onWindowInfosChanged(
9880 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9881 {},
9882 0,
9883 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009884 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009885 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009886
Antonio Kantek15beb512022-06-13 22:35:41 +00009887 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009888 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009889 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009890 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9891 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009892 mThirdWindow->assertNoEvents();
9893 }
9894
9895 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9896 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009897 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009898 SECOND_DISPLAY_ID)) {
9899 mWindow->assertNoEvents();
9900 mSecondWindow->assertNoEvents();
9901 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009902 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009903 }
9904
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009905 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009906 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009907 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9908 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009909 mWindow->consumeTouchModeEvent(inTouchMode);
9910 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009911 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009912 }
9913};
9914
Antonio Kantek26defcf2022-02-08 01:12:27 +00009915TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009916 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009917 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9918 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009919 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009920}
9921
Antonio Kantek26defcf2022-02-08 01:12:27 +00009922TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9923 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009924 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009925 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009926 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009927 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009928 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009929 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009930 mWindow->assertNoEvents();
9931 mSecondWindow->assertNoEvents();
9932}
9933
9934TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9935 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009936 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009937 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009938 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009939 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009940 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009941}
9942
Antonio Kantekf16f2832021-09-28 04:39:20 +00009943TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009944 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009945 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9946 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009947 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009948 mWindow->assertNoEvents();
9949 mSecondWindow->assertNoEvents();
9950}
9951
Antonio Kantek15beb512022-06-13 22:35:41 +00009952TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9953 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9954 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9955 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009956 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009957 mWindow->assertNoEvents();
9958 mSecondWindow->assertNoEvents();
9959 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9960}
9961
Antonio Kantek48710e42022-03-24 14:19:30 -07009962TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9963 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9965 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009966 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9967 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9968
9969 // Then remove focus.
9970 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009971 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009972
9973 // Assert that caller can switch touch mode by owning one of the last interacted window.
9974 const WindowInfo& windowInfo = *mWindow->getInfo();
9975 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9976 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009977 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009978}
9979
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009980class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9981public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009982 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009983 std::shared_ptr<FakeApplicationHandle> application =
9984 std::make_shared<FakeApplicationHandle>();
9985 std::string name = "Fake Spy ";
9986 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009987 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9988 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009989 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009990 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009991 return spy;
9992 }
9993
9994 sp<FakeWindowHandle> createForeground() {
9995 std::shared_ptr<FakeApplicationHandle> application =
9996 std::make_shared<FakeApplicationHandle>();
9997 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009998 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9999 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010000 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010001 return window;
10002 }
10003
10004private:
10005 int mSpyCount{0};
10006};
10007
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010008using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010009/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010010 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10011 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010012TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010013 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010014 ScopedSilentDeath _silentDeath;
10015
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010016 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010017 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010018 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010019 ".* not a trusted overlay");
10020}
10021
10022/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010023 * Input injection into a display with a spy window but no foreground windows should succeed.
10024 */
10025TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010026 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010027 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010028
10029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010030 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10032 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10033}
10034
10035/**
10036 * Verify the order in which different input windows receive events. The touched foreground window
10037 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10038 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10039 * receive events before ones belows it.
10040 *
10041 * Here, we set up a scenario with four windows in the following Z order from the top:
10042 * spy1, spy2, window, spy3.
10043 * We then inject an event and verify that the foreground "window" receives it first, followed by
10044 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10045 * window.
10046 */
10047TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10048 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010049 auto spy1 = createSpy();
10050 auto spy2 = createSpy();
10051 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010052 mDispatcher->onWindowInfosChanged(
10053 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010054 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10055 const size_t numChannels = channels.size();
10056
Michael Wright8e9a8562022-02-09 13:44:29 +000010057 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010058 if (!epollFd.ok()) {
10059 FAIL() << "Failed to create epoll fd";
10060 }
10061
10062 for (size_t i = 0; i < numChannels; i++) {
10063 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10064 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10065 FAIL() << "Failed to add fd to epoll";
10066 }
10067 }
10068
10069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010070 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10072
10073 std::vector<size_t> eventOrder;
10074 std::vector<struct epoll_event> events(numChannels);
10075 for (;;) {
10076 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10077 (100ms).count());
10078 if (nFds < 0) {
10079 FAIL() << "Failed to call epoll_wait";
10080 }
10081 if (nFds == 0) {
10082 break; // epoll_wait timed out
10083 }
10084 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010085 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010086 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010087 channels[i]->consumeMotionDown();
10088 }
10089 }
10090
10091 // Verify the order in which the events were received.
10092 EXPECT_EQ(3u, eventOrder.size());
10093 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10094 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10095 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10096}
10097
10098/**
10099 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10100 */
10101TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10102 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010103 auto spy = createSpy();
10104 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010105 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010106
10107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010108 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10110 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10111 spy->assertNoEvents();
10112}
10113
10114/**
10115 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10116 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10117 * to the window.
10118 */
10119TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10120 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010121 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010122 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010123 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010124
10125 // Inject an event outside the spy window's touchable region.
10126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010127 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10129 window->consumeMotionDown();
10130 spy->assertNoEvents();
10131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010132 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10134 window->consumeMotionUp();
10135 spy->assertNoEvents();
10136
10137 // Inject an event inside the spy window's touchable region.
10138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010139 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010140 {5, 10}))
10141 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10142 window->consumeMotionDown();
10143 spy->consumeMotionDown();
10144}
10145
10146/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010147 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010148 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010149 */
10150TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10151 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010152 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010153 auto spy = createSpy();
10154 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010155 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010156 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010157 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010158
10159 // Inject an event outside the spy window's frame and touchable region.
10160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010161 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010162 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010163 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10164 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010165 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010166}
10167
10168/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010169 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10170 * pointers that are down within its bounds.
10171 */
10172TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10173 auto windowLeft = createForeground();
10174 windowLeft->setFrame({0, 0, 100, 200});
10175 auto windowRight = createForeground();
10176 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010177 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010178 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010179 mDispatcher->onWindowInfosChanged(
10180 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010181
10182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010184 {50, 50}))
10185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10186 windowLeft->consumeMotionDown();
10187 spy->consumeMotionDown();
10188
10189 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010190 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010191 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010192 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10193 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010194 .build();
10195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010196 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010197 InputEventInjectionSync::WAIT_FOR_RESULT))
10198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10199 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010200 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010201}
10202
10203/**
10204 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10205 * the spy should receive the second pointer with ACTION_DOWN.
10206 */
10207TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10208 auto window = createForeground();
10209 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010210 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010211 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010212 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010213
10214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010215 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010216 {50, 50}))
10217 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10218 window->consumeMotionDown();
10219 spyRight->assertNoEvents();
10220
10221 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010222 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010223 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010224 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10225 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010226 .build();
10227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010228 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010229 InputEventInjectionSync::WAIT_FOR_RESULT))
10230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010231 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010232 spyRight->consumeMotionDown();
10233}
10234
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010235/**
10236 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10237 * windows should be allowed to control split touch.
10238 */
10239TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010240 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010241 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010242 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010243 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010244
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010245 auto window = createForeground();
10246 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010247
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010248 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010249
10250 // First finger down, no window touched.
10251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010252 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010253 {100, 200}))
10254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10255 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10256 window->assertNoEvents();
10257
10258 // Second finger down on window, the window should receive touch down.
10259 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010260 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010261 .displayId(ADISPLAY_ID_DEFAULT)
10262 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010263 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10264 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010265 .build();
10266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010267 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010268 InputEventInjectionSync::WAIT_FOR_RESULT))
10269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10270
10271 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010272 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010273}
10274
10275/**
10276 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10277 * do not receive key events.
10278 */
10279TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010280 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010281 spy->setFocusable(false);
10282
10283 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010285 setFocusedWindow(window);
10286 window->consumeFocusEvent(true);
10287
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010289 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10290 window->consumeKeyDown(ADISPLAY_ID_NONE);
10291
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010293 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10294 window->consumeKeyUp(ADISPLAY_ID_NONE);
10295
10296 spy->assertNoEvents();
10297}
10298
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010299using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10300
10301/**
10302 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10303 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10304 */
10305TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10306 auto window = createForeground();
10307 auto spy1 = createSpy();
10308 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010309 mDispatcher->onWindowInfosChanged(
10310 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010311
10312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010313 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10315 window->consumeMotionDown();
10316 spy1->consumeMotionDown();
10317 spy2->consumeMotionDown();
10318
10319 // Pilfer pointers from the second spy window.
10320 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10321 spy2->assertNoEvents();
10322 spy1->consumeMotionCancel();
10323 window->consumeMotionCancel();
10324
10325 // The rest of the gesture should only be sent to the second spy window.
10326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010327 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010328 ADISPLAY_ID_DEFAULT))
10329 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10330 spy2->consumeMotionMove();
10331 spy1->assertNoEvents();
10332 window->assertNoEvents();
10333}
10334
10335/**
10336 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10337 * in the middle of the gesture.
10338 */
10339TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10340 auto window = createForeground();
10341 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010342 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010343
10344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010345 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10347 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10348 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10349
10350 window->releaseChannel();
10351
10352 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10353
10354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010355 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10357 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10358}
10359
10360/**
10361 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10362 * the spy, but not to any other windows.
10363 */
10364TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10365 auto spy = createSpy();
10366 auto window = createForeground();
10367
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010368 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010369
10370 // First finger down on the window and the spy.
10371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010372 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010373 {100, 200}))
10374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10375 spy->consumeMotionDown();
10376 window->consumeMotionDown();
10377
10378 // Spy window pilfers the pointers.
10379 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10380 window->consumeMotionCancel();
10381
10382 // Second finger down on the window and spy, but the window should not receive the pointer down.
10383 const MotionEvent secondFingerDownEvent =
10384 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10385 .displayId(ADISPLAY_ID_DEFAULT)
10386 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010387 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10388 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010389 .build();
10390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010391 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010392 InputEventInjectionSync::WAIT_FOR_RESULT))
10393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10394
Harry Cutts33476232023-01-30 19:57:29 +000010395 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010396
10397 // Third finger goes down outside all windows, so injection should fail.
10398 const MotionEvent thirdFingerDownEvent =
10399 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10400 .displayId(ADISPLAY_ID_DEFAULT)
10401 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010402 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10403 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10404 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010405 .build();
10406 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010407 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010408 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010409 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010410
10411 spy->assertNoEvents();
10412 window->assertNoEvents();
10413}
10414
10415/**
10416 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10417 */
10418TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10419 auto spy = createSpy();
10420 spy->setFrame(Rect(0, 0, 100, 100));
10421 auto window = createForeground();
10422 window->setFrame(Rect(0, 0, 200, 200));
10423
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010424 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010425
10426 // First finger down on the window only
10427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010429 {150, 150}))
10430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10431 window->consumeMotionDown();
10432
10433 // Second finger down on the spy and window
10434 const MotionEvent secondFingerDownEvent =
10435 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10436 .displayId(ADISPLAY_ID_DEFAULT)
10437 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010438 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10439 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010440 .build();
10441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010442 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010443 InputEventInjectionSync::WAIT_FOR_RESULT))
10444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10445 spy->consumeMotionDown();
10446 window->consumeMotionPointerDown(1);
10447
10448 // Third finger down on the spy and window
10449 const MotionEvent thirdFingerDownEvent =
10450 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10451 .displayId(ADISPLAY_ID_DEFAULT)
10452 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010453 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10454 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10455 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010456 .build();
10457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010458 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010459 InputEventInjectionSync::WAIT_FOR_RESULT))
10460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10461 spy->consumeMotionPointerDown(1);
10462 window->consumeMotionPointerDown(2);
10463
10464 // Spy window pilfers the pointers.
10465 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010466 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10467 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010468
10469 spy->assertNoEvents();
10470 window->assertNoEvents();
10471}
10472
10473/**
10474 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10475 * other windows should be canceled. If this results in the cancellation of all pointers for some
10476 * window, then that window should receive ACTION_CANCEL.
10477 */
10478TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10479 auto spy = createSpy();
10480 spy->setFrame(Rect(0, 0, 100, 100));
10481 auto window = createForeground();
10482 window->setFrame(Rect(0, 0, 200, 200));
10483
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010484 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010485
10486 // First finger down on both spy and window
10487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010488 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010489 {10, 10}))
10490 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10491 window->consumeMotionDown();
10492 spy->consumeMotionDown();
10493
10494 // Second finger down on the spy and window
10495 const MotionEvent secondFingerDownEvent =
10496 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10497 .displayId(ADISPLAY_ID_DEFAULT)
10498 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010499 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10500 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010501 .build();
10502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010503 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010504 InputEventInjectionSync::WAIT_FOR_RESULT))
10505 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10506 spy->consumeMotionPointerDown(1);
10507 window->consumeMotionPointerDown(1);
10508
10509 // Spy window pilfers the pointers.
10510 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10511 window->consumeMotionCancel();
10512
10513 spy->assertNoEvents();
10514 window->assertNoEvents();
10515}
10516
10517/**
10518 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10519 * be sent to other windows
10520 */
10521TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10522 auto spy = createSpy();
10523 spy->setFrame(Rect(0, 0, 100, 100));
10524 auto window = createForeground();
10525 window->setFrame(Rect(0, 0, 200, 200));
10526
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010527 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010528
10529 // First finger down on both window and spy
10530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010531 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010532 {10, 10}))
10533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10534 window->consumeMotionDown();
10535 spy->consumeMotionDown();
10536
10537 // Spy window pilfers the pointers.
10538 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10539 window->consumeMotionCancel();
10540
10541 // Second finger down on the window only
10542 const MotionEvent secondFingerDownEvent =
10543 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10544 .displayId(ADISPLAY_ID_DEFAULT)
10545 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010546 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10547 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010548 .build();
10549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010550 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010551 InputEventInjectionSync::WAIT_FOR_RESULT))
10552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10553 window->consumeMotionDown();
10554 window->assertNoEvents();
10555
10556 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10557 spy->consumeMotionMove();
10558 spy->assertNoEvents();
10559}
10560
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010561/**
10562 * A window on the left and a window on the right. Also, a spy window that's above all of the
10563 * windows, and spanning both left and right windows.
10564 * Send simultaneous motion streams from two different devices, one to the left window, and another
10565 * to the right window.
10566 * Pilfer from spy window.
10567 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10568 */
10569TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10570 sp<FakeWindowHandle> spy = createSpy();
10571 spy->setFrame(Rect(0, 0, 200, 200));
10572 sp<FakeWindowHandle> leftWindow = createForeground();
10573 leftWindow->setFrame(Rect(0, 0, 100, 100));
10574
10575 sp<FakeWindowHandle> rightWindow = createForeground();
10576 rightWindow->setFrame(Rect(100, 0, 200, 100));
10577
10578 constexpr int32_t stylusDeviceId = 1;
10579 constexpr int32_t touchDeviceId = 2;
10580
10581 mDispatcher->onWindowInfosChanged(
10582 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10583
10584 // Stylus down on left window and spy
10585 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10586 .deviceId(stylusDeviceId)
10587 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10588 .build());
10589 leftWindow->consumeMotionEvent(
10590 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10591 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10592
10593 // Finger down on right window and spy - but spy already has stylus
10594 mDispatcher->notifyMotion(
10595 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10596 .deviceId(touchDeviceId)
10597 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10598 .build());
10599 rightWindow->consumeMotionEvent(
10600 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010601 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010602
10603 // Act: pilfer from spy. Spy is currently receiving touch events.
10604 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010605 leftWindow->consumeMotionEvent(
10606 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010607 rightWindow->consumeMotionEvent(
10608 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10609
10610 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10611 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10612 .deviceId(stylusDeviceId)
10613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10614 .build());
10615 mDispatcher->notifyMotion(
10616 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10617 .deviceId(touchDeviceId)
10618 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10619 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010620 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010621
10622 spy->assertNoEvents();
10623 leftWindow->assertNoEvents();
10624 rightWindow->assertNoEvents();
10625}
10626
Prabir Pradhand65552b2021-10-07 11:23:50 -070010627class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10628public:
10629 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10630 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10631 std::make_shared<FakeApplicationHandle>();
10632 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010633 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10634 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010635 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010636 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010637 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010638 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010639 overlay->setTrustedOverlay(true);
10640
10641 std::shared_ptr<FakeApplicationHandle> application =
10642 std::make_shared<FakeApplicationHandle>();
10643 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010644 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10645 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010646 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010647 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010648
10649 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010650 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010651 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010652 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010653 return {std::move(overlay), std::move(window)};
10654 }
10655
10656 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010657 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010658 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010659 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010660 }
10661
10662 void sendStylusEvent(int32_t action) {
10663 NotifyMotionArgs motionArgs =
10664 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10665 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010666 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010667 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010668 }
10669};
10670
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010671using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10672
10673TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010674 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010675 ScopedSilentDeath _silentDeath;
10676
Prabir Pradhand65552b2021-10-07 11:23:50 -070010677 auto [overlay, window] = setupStylusOverlayScenario();
10678 overlay->setTrustedOverlay(false);
10679 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010680 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10681 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010682 ".* not a trusted overlay");
10683}
10684
10685TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10686 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010687 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010688
10689 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10690 overlay->consumeMotionDown();
10691 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10692 overlay->consumeMotionUp();
10693
10694 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10695 window->consumeMotionDown();
10696 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10697 window->consumeMotionUp();
10698
10699 overlay->assertNoEvents();
10700 window->assertNoEvents();
10701}
10702
10703TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10704 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010705 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010706 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010707
10708 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10709 overlay->consumeMotionDown();
10710 window->consumeMotionDown();
10711 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10712 overlay->consumeMotionUp();
10713 window->consumeMotionUp();
10714
10715 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10716 window->consumeMotionDown();
10717 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10718 window->consumeMotionUp();
10719
10720 overlay->assertNoEvents();
10721 window->assertNoEvents();
10722}
10723
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010724/**
10725 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10726 * The scenario is as follows:
10727 * - The stylus interceptor overlay is configured as a spy window.
10728 * - The stylus interceptor spy receives the start of a new stylus gesture.
10729 * - It pilfers pointers and then configures itself to no longer be a spy.
10730 * - The stylus interceptor continues to receive the rest of the gesture.
10731 */
10732TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10733 auto [overlay, window] = setupStylusOverlayScenario();
10734 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010735 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010736
10737 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10738 overlay->consumeMotionDown();
10739 window->consumeMotionDown();
10740
10741 // The interceptor pilfers the pointers.
10742 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10743 window->consumeMotionCancel();
10744
10745 // The interceptor configures itself so that it is no longer a spy.
10746 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010747 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010748
10749 // It continues to receive the rest of the stylus gesture.
10750 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10751 overlay->consumeMotionMove();
10752 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10753 overlay->consumeMotionUp();
10754
10755 window->assertNoEvents();
10756}
10757
Prabir Pradhan5735a322022-04-11 17:23:34 +000010758struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010759 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010760 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010761 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10762 std::unique_ptr<InputDispatcher>& mDispatcher;
10763
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010764 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010765 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10766
10767 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010768 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010769 ADISPLAY_ID_DEFAULT, {100, 200},
10770 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10771 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10772 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10773 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10774 }
10775
10776 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010777 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010778 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010779 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010780 mPolicyFlags);
10781 }
10782
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010783 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010784 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10785 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10787 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010788 window->setOwnerInfo(mPid, mUid);
10789 return window;
10790 }
10791};
10792
10793using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10794
10795TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010796 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010797 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010799
10800 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10801 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10802 window->consumeMotionDown();
10803
10804 setFocusedWindow(window);
10805 window->consumeFocusEvent(true);
10806
10807 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10808 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10809 window->consumeKeyDown(ADISPLAY_ID_NONE);
10810}
10811
10812TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010813 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010814 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010816
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010817 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010818 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10819 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10820
10821 setFocusedWindow(window);
10822 window->consumeFocusEvent(true);
10823
10824 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10825 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10826 window->assertNoEvents();
10827}
10828
10829TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010830 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010831 auto window = owner.createWindow("Owned window");
10832 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010833 spy->setSpy(true);
10834 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010835 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010836
10837 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10838 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10839 spy->consumeMotionDown();
10840 window->consumeMotionDown();
10841}
10842
10843TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010844 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010845 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010846
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010847 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010848 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010849 randosSpy->setSpy(true);
10850 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010851 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010852
10853 // The event is targeted at owner's window, so injection should succeed, but the spy should
10854 // not receive the event.
10855 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10856 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10857 randosSpy->assertNoEvents();
10858 window->consumeMotionDown();
10859}
10860
10861TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010862 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010863 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010864
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010865 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010866 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010867 randosSpy->setSpy(true);
10868 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010869 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010870
10871 // A user that has injection permission can inject into any window.
10872 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010873 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010874 ADISPLAY_ID_DEFAULT));
10875 randosSpy->consumeMotionDown();
10876 window->consumeMotionDown();
10877
10878 setFocusedWindow(randosSpy);
10879 randosSpy->consumeFocusEvent(true);
10880
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010881 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010882 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10883 window->assertNoEvents();
10884}
10885
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010886TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010887 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010888 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010889
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010890 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010891 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010892 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10893 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010894 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010895
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010896 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010897 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10898 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10899 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010900 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010901}
10902
Garfield Tane84e6f92019-08-29 17:28:41 -070010903} // namespace android::inputdispatcher