blob: 3c2b31d770d2ce3c2fe31591e5f96ac1ec9592e3 [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);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000338 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800339 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
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000369 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
370 std::scoped_lock lock(mLock);
371 mUnhandledKeyHandler = handler;
372 }
373
374 void assertUnhandledKeyReported(int32_t keycode) {
375 std::unique_lock lock(mLock);
376 base::ScopedLockAssertion assumeLocked(mLock);
377 std::optional<int32_t> unhandledKeycode =
378 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
379 mNotifyUnhandledKey);
380 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
381 ASSERT_EQ(unhandledKeycode, keycode);
382 }
383
384 void assertUnhandledKeyNotReported() {
385 std::unique_lock lock(mLock);
386 base::ScopedLockAssertion assumeLocked(mLock);
387 std::optional<int32_t> unhandledKeycode =
388 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
389 mNotifyUnhandledKey);
390 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
391 }
392
Michael Wrightd02c5b62014-02-10 15:10:22 -0800393private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700394 std::mutex mLock;
395 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
396 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
397 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
398 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800399
Prabir Pradhan99987712020-11-10 18:43:05 -0800400 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000401
402 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800403
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700404 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700405 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800406 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
407 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700408 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800409 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
410 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411
arthurhungf452d0b2021-01-06 00:19:52 +0800412 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800413 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000414 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800415
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800416 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
417
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700418 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
419
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000420 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000421
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000422 std::condition_variable mNotifyUnhandledKey;
423 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
424 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
425
Prabir Pradhanedd96402022-02-15 01:46:16 -0800426 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
427 // for a specific container to become non-empty. When the container is non-empty, return the
428 // first entry from the container and erase it.
429 template <class T>
430 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
431 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
432 // If there is an ANR, Dispatcher won't be idle because there are still events
433 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
434 // before checking if ANR was called.
435 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
436 // to provide it some time to act. 100ms seems reasonable.
437 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
438 const std::chrono::time_point start = std::chrono::steady_clock::now();
439 std::optional<T> token =
440 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
441 if (!token.has_value()) {
442 ADD_FAILURE() << "Did not receive the ANR callback";
443 return {};
444 }
445
446 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
447 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
448 // the dispatcher started counting before this function was called
449 if (std::chrono::abs(timeout - waited) > 100ms) {
450 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
451 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
452 << "ms, but waited "
453 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
454 << "ms instead";
455 }
456 return *token;
457 }
458
459 template <class T>
460 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
461 std::queue<T>& storage,
462 std::unique_lock<std::mutex>& lock,
463 std::condition_variable& condition)
464 REQUIRES(mLock) {
465 condition.wait_for(lock, timeout,
466 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
467 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800468 return std::nullopt;
469 }
470 T item = storage.front();
471 storage.pop();
472 return std::make_optional(item);
473 }
474
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600475 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700476 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800477 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800478 }
479
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000480 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800481 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700482 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800483 ASSERT_TRUE(pid.has_value());
484 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500486 }
487
Prabir Pradhanedd96402022-02-15 01:46:16 -0800488 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000489 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500490 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 ASSERT_TRUE(pid.has_value());
492 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 mNotifyAnr.notify_all();
494 }
495
496 void notifyNoFocusedWindowAnr(
497 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
498 std::scoped_lock lock(mLock);
499 mAnrApplications.push(applicationHandle);
500 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 }
502
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800503 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
504 std::scoped_lock lock(mLock);
505 mBrokenInputChannels.push(connectionToken);
506 mNotifyInputChannelBroken.notify_all();
507 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800508
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600509 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700510
Chris Yef59a2f42020-10-16 12:55:26 -0700511 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
512 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
513 const std::vector<float>& values) override {}
514
515 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
516 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000517
Chris Yefb552902021-02-03 17:18:37 -0800518 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
519
Prabir Pradhana41d2442023-04-20 21:30:40 +0000520 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700521 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000522 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700523 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000524 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
525 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800526 break;
527 }
528
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700529 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000530 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
531 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800532 break;
533 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700534 default: {
535 ADD_FAILURE() << "Should only filter keys or motions";
536 break;
537 }
Jackal Guof9696682018-10-05 12:23:23 +0800538 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800539 return true;
540 }
541
Prabir Pradhana41d2442023-04-20 21:30:40 +0000542 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
543 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800544 // Clear intercept state when we handled the event.
545 mInterceptKeyTimeout = 0ms;
546 }
547 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800548
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600549 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550
Prabir Pradhana41d2442023-04-20 21:30:40 +0000551 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800552 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
553 // Clear intercept state so we could dispatch the event in next wake.
554 mInterceptKeyTimeout = 0ms;
555 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556 }
557
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000558 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000559 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000560 std::scoped_lock lock(mLock);
561 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
562 mNotifyUnhandledKey.notify_all();
563 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800564 }
565
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600566 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
567 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700568 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800569 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
570 * essentially a passthrough for notifySwitch.
571 */
Harry Cutts33476232023-01-30 19:57:29 +0000572 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573 }
574
Josep del Riob3981622023-04-18 15:49:45 +0000575 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
576 std::scoped_lock lock(mLock);
577 mPokedUserActivity = true;
578 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700580 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
581 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
582 }
583
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600584 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700585 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700586 mOnPointerDownToken = newToken;
587 }
588
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000589 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800590 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000591 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800592 mPointerCaptureChangedCondition.notify_all();
593 }
594
arthurhungf452d0b2021-01-06 00:19:52 +0800595 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
596 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800597 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800598 mDropTargetWindowToken = token;
599 }
600
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000601 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000602 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000603 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
604 }
605
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700606 void assertFilterInputEventWasCalledInternal(
607 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700608 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800609 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700610 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800611 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800612 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700614} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616// --- InputDispatcherTest ---
617
618class InputDispatcherTest : public testing::Test {
619protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000620 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700621 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000623 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700625 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
626
Harry Cutts101ee9b2023-07-06 18:04:14 +0000627 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000628 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700629 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630 }
631
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000632 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000634 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700635 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700637
638 /**
639 * Used for debugging when writing the test
640 */
641 void dumpDispatcherState() {
642 std::string dump;
643 mDispatcher->dump(dump);
644 std::stringstream ss(dump);
645 std::string to;
646
647 while (std::getline(ss, to, '\n')) {
648 ALOGE("%s", to.c_str());
649 }
650 }
Vishnu Nair958da932020-08-21 17:12:37 -0700651
Chavi Weingarten847e8512023-03-29 00:26:09 +0000652 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700653 FocusRequest request;
654 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000655 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700656 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
657 request.displayId = window->getInfo()->displayId;
658 mDispatcher->setFocusedWindow(request);
659 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660};
661
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
663 KeyEvent event;
664
665 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800666 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
667 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000668 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600669 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800670 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000671 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000672 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800673 << "Should reject key events with undefined action.";
674
675 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800676 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
677 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600678 ARBITRARY_TIME, ARBITRARY_TIME);
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 key events with ACTION_MULTIPLE.";
683}
684
685TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
686 MotionEvent event;
687 PointerProperties pointerProperties[MAX_POINTERS + 1];
688 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800689 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 pointerProperties[i].clear();
691 pointerProperties[i].id = i;
692 pointerCoords[i].clear();
693 }
694
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800695 // Some constants commonly used below
696 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
697 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
698 constexpr int32_t metaState = AMETA_NONE;
699 constexpr MotionClassification classification = MotionClassification::NONE;
700
chaviw9eaa22c2020-07-01 16:21:27 -0700701 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800702 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800703 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000704 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700705 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700706 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
707 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800709 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000710 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000711 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800712 << "Should reject motion events with undefined action.";
713
714 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800715 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800716 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
717 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
718 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
719 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000720 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800721 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000722 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000723 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800724 << "Should reject motion events with pointer down index too large.";
725
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700727 AMOTION_EVENT_ACTION_POINTER_DOWN |
728 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700729 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
730 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700731 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000732 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800733 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000734 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000735 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800736 << "Should reject motion events with pointer down index too small.";
737
738 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800739 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800740 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
741 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
742 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
743 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000744 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800745 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000746 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000747 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800748 << "Should reject motion events with pointer up index too large.";
749
Garfield Tanfbe732e2020-01-24 11:26:14 -0800750 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700751 AMOTION_EVENT_ACTION_POINTER_UP |
752 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700753 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
754 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700755 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000756 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000758 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000759 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800760 << "Should reject motion events with pointer up index too small.";
761
762 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800763 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
764 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700765 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700766 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
767 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000768 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800769 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000770 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000771 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800772 << "Should reject motion events with 0 pointers.";
773
Garfield Tanfbe732e2020-01-24 11:26:14 -0800774 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
775 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700776 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700777 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
778 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000779 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000781 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000782 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800783 << "Should reject motion events with more than MAX_POINTERS pointers.";
784
785 // Rejects motion events with invalid pointer ids.
786 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800787 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
788 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700789 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700790 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
791 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000792 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800793 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000794 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000795 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800796 << "Should reject motion events with pointer ids less than 0.";
797
798 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800799 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
800 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700801 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700802 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
803 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000804 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800805 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000806 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000807 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800808 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
809
810 // Rejects motion events with duplicate pointer ids.
811 pointerProperties[0].id = 1;
812 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800813 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
814 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700815 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700816 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
817 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000818 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800819 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000820 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000821 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800822 << "Should reject motion events with duplicate pointer ids.";
823}
824
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800825/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
826
827TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
828 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000829 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800830 ASSERT_TRUE(mDispatcher->waitForIdle());
831
832 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
833}
834
835TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000836 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
837 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000838 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800839
840 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
841 args.policyFlags |= POLICY_FLAG_TRUSTED;
842 mFakePolicy->assertNotifySwitchWasCalled(args);
843}
844
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700845namespace {
846
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700847static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700848// Default input dispatching timeout if there is no focused application or paused window
849// from which to determine an appropriate dispatching timeout.
850static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
851 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
852 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800853
854class FakeApplicationHandle : public InputApplicationHandle {
855public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700856 FakeApplicationHandle() {
857 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700858 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500859 mInfo.dispatchingTimeoutMillis =
860 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800862 virtual ~FakeApplicationHandle() {}
863
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000864 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500866 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
867 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700868 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800869};
870
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800871class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800872public:
Garfield Tan15601662020-09-22 15:32:38 -0700873 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800874 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700875 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800876 }
877
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000878 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700879 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700880 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 if (!consumeSeq) {
882 return nullptr;
883 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000884 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 return event;
886 }
887
888 /**
889 * Receive an event without acknowledging it.
890 * Return the sequence number that could later be used to send finished signal.
891 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700892 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
893 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800894 uint32_t consumeSeq;
895 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800896
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800897 std::chrono::time_point start = std::chrono::steady_clock::now();
898 status_t status = WOULD_BLOCK;
899 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000900 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800901 &event);
902 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700903 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800904 break;
905 }
906 }
907
908 if (status == WOULD_BLOCK) {
909 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800911 }
912
913 if (status != OK) {
914 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700915 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800916 }
917 if (event == nullptr) {
918 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700919 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700921 if (outEvent != nullptr) {
922 *outEvent = event;
923 }
924 return consumeSeq;
925 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800926
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700927 /**
928 * To be used together with "receiveEvent" to complete the consumption of an event.
929 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000930 void finishEvent(uint32_t consumeSeq, bool handled = true) {
931 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 }
934
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000935 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
936 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
937 ASSERT_EQ(OK, status);
938 }
939
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700940 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000941 std::optional<int32_t> expectedDisplayId,
942 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700943 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800944
945 ASSERT_NE(nullptr, event) << mName.c_str()
946 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800947 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700948 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
949 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800950
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000951 if (expectedDisplayId.has_value()) {
952 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
953 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800954
Tiger Huang8664f8c2018-10-11 19:14:35 +0800955 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800957 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700958 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000959 if (expectedFlags.has_value()) {
960 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
961 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800962 break;
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800965 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700966 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000967 if (expectedFlags.has_value()) {
968 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 break;
971 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100973 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
974 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700975 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800976 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
977 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700978 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000979 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800982 FAIL() << "Use 'consumeDragEvent' for DRAG events";
983 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800984 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800985 }
986
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800987 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700988 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800989
990 if (event == nullptr) {
991 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
992 return nullptr;
993 }
994
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700995 if (event->getType() != InputEventType::MOTION) {
996 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800997 return nullptr;
998 }
999 return static_cast<MotionEvent*>(event);
1000 }
1001
1002 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1003 MotionEvent* motionEvent = consumeMotion();
1004 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1005 ASSERT_THAT(*motionEvent, matcher);
1006 }
1007
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001008 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001009 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001010 ASSERT_NE(nullptr, event) << mName.c_str()
1011 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1013 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001014
1015 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1016 << mName.c_str() << ": event displayId should always be NONE.";
1017
1018 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1019 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001020 }
1021
Prabir Pradhan99987712020-11-10 18:43:05 -08001022 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001023 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001024 ASSERT_NE(nullptr, event) << mName.c_str()
1025 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001026 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1027 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001028
1029 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1030 << mName.c_str() << ": event displayId should always be NONE.";
1031
1032 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1033 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1034 }
1035
arthurhungb89ccb02020-12-30 16:19:01 +08001036 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001037 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001038 ASSERT_NE(nullptr, event) << mName.c_str()
1039 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001040 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001041
1042 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1043 << mName.c_str() << ": event displayId should always be NONE.";
1044
1045 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1046 EXPECT_EQ(isExiting, dragEvent.isExiting());
1047 EXPECT_EQ(x, dragEvent.getX());
1048 EXPECT_EQ(y, dragEvent.getY());
1049 }
1050
Antonio Kantekf16f2832021-09-28 04:39:20 +00001051 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001052 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001053 ASSERT_NE(nullptr, event) << mName.c_str()
1054 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1056 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001057
1058 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1059 << mName.c_str() << ": event displayId should always be NONE.";
1060 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1061 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1062 }
1063
chaviwd1c23182019-12-20 18:44:56 -08001064 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001065 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001066 if (event == nullptr) {
1067 return;
1068 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001070 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1071 ADD_FAILURE() << "Received key event "
1072 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001074 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1075 ADD_FAILURE() << "Received motion event "
1076 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001077 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001078 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1079 ADD_FAILURE() << "Received focus event, hasFocus = "
1080 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001081 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001082 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1083 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1084 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001085 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001086 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1087 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1088 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001089 }
1090 FAIL() << mName.c_str()
1091 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001092 }
1093
1094 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1095
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001096 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1097
chaviwd1c23182019-12-20 18:44:56 -08001098protected:
1099 std::unique_ptr<InputConsumer> mConsumer;
1100 PreallocatedInputEventFactory mEventFactory;
1101
1102 std::string mName;
1103};
1104
chaviw3277faf2021-05-19 16:45:23 -05001105class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001106public:
1107 static const int32_t WIDTH = 600;
1108 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001109
Chris Yea209fde2020-07-22 13:54:51 -07001110 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001111 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001112 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001113 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001114 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001115 base::Result<std::unique_ptr<InputChannel>> channel =
1116 dispatcher->createInputChannel(name);
1117 token = (*channel)->getConnectionToken();
1118 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001119 }
1120
1121 inputApplicationHandle->updateInfo();
1122 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1123
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001124 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001125 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001126 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001127 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001128 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001129 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001130 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.globalScaleFactor = 1.0;
1132 mInfo.touchableRegion.clear();
1133 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001134 mInfo.ownerPid = WINDOW_PID;
1135 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001136 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001137 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001138 }
1139
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001140 sp<FakeWindowHandle> clone(int32_t displayId) {
1141 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1142 handle->mInfo = mInfo;
1143 handle->mInfo.displayId = displayId;
1144 handle->mInfo.id = sId++;
1145 handle->mInputReceiver = mInputReceiver;
1146 return handle;
1147 }
1148
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001149 void setTouchable(bool touchable) {
1150 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1151 }
chaviwd1c23182019-12-20 18:44:56 -08001152
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001153 void setFocusable(bool focusable) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1155 }
1156
1157 void setVisible(bool visible) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1159 }
Vishnu Nair958da932020-08-21 17:12:37 -07001160
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001161 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001162 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001163 }
1164
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001165 void setPaused(bool paused) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1167 }
1168
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001169 void setPreventSplitting(bool preventSplitting) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001171 }
1172
1173 void setSlippery(bool slippery) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1175 }
1176
1177 void setWatchOutsideTouch(bool watchOutside) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1179 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001180
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001181 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1182
1183 void setInterceptsStylus(bool interceptsStylus) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1185 }
1186
1187 void setDropInput(bool dropInput) {
1188 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1189 }
1190
1191 void setDropInputIfObscured(bool dropInputIfObscured) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1193 }
1194
1195 void setNoInputChannel(bool noInputChannel) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1197 }
1198
Josep del Riob3981622023-04-18 15:49:45 +00001199 void setDisableUserActivity(bool disableUserActivity) {
1200 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1201 }
1202
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001203 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1204
chaviw3277faf2021-05-19 16:45:23 -05001205 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001206
Bernardo Rufino7393d172021-02-26 13:56:11 +00001207 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1208
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001209 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001210 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001211 mInfo.touchableRegion.clear();
1212 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001213
1214 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1215 ui::Transform translate;
1216 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1217 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001218 }
1219
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001220 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1221
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001222 void setIsWallpaper(bool isWallpaper) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1224 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001225
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001226 void setDupTouchToWallpaper(bool hasWallpaper) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1228 }
chaviwd1c23182019-12-20 18:44:56 -08001229
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001230 void setTrustedOverlay(bool trustedOverlay) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1232 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001233
chaviw9eaa22c2020-07-01 16:21:27 -07001234 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1235 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1236 }
1237
1238 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001239
yunho.shinf4a80b82020-11-16 21:13:57 +09001240 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1241
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001242 KeyEvent* consumeKey(bool handled = true) {
1243 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001244 if (event == nullptr) {
1245 ADD_FAILURE() << "Consume failed : no event";
1246 return nullptr;
1247 }
1248 if (event->getType() != InputEventType::KEY) {
1249 ADD_FAILURE() << "Instead of key event, got " << *event;
1250 return nullptr;
1251 }
1252 return static_cast<KeyEvent*>(event);
1253 }
1254
1255 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1256 KeyEvent* keyEvent = consumeKey();
1257 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1258 ASSERT_THAT(*keyEvent, matcher);
1259 }
1260
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001261 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001262 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001263 }
1264
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001265 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001266 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001267 }
1268
Svet Ganov5d3bc372020-01-26 23:11:07 -08001269 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001270 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001271 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1272 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001273 }
1274
1275 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001277 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1278 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001279 }
1280
1281 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001282 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001283 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1284 }
1285
1286 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1287 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001288 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001289 expectedFlags);
1290 }
1291
Svet Ganov5d3bc372020-01-26 23:11:07 -08001292 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1294 int32_t expectedFlags = 0) {
1295 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1296 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001298 }
1299
1300 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001301 int32_t expectedFlags = 0) {
1302 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1303 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001304 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001305 }
1306
1307 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001308 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001309 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001310 expectedFlags);
1311 }
1312
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001313 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1314 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001315 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001316 expectedFlags);
1317 }
1318
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001319 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1320 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001321 MotionEvent* motionEvent = consumeMotion();
1322 ASSERT_NE(nullptr, motionEvent);
1323 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1324 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1325 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001326 }
1327
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001328 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1329 ASSERT_NE(mInputReceiver, nullptr)
1330 << "Cannot consume events from a window with no receiver";
1331 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1332 }
1333
Prabir Pradhan99987712020-11-10 18:43:05 -08001334 void consumeCaptureEvent(bool hasCapture) {
1335 ASSERT_NE(mInputReceiver, nullptr)
1336 << "Cannot consume events from a window with no receiver";
1337 mInputReceiver->consumeCaptureEvent(hasCapture);
1338 }
1339
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001340 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1341 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001342 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001343 ASSERT_THAT(*motionEvent, matcher);
1344 }
1345
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001346 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001347 std::optional<int32_t> expectedDisplayId,
1348 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001349 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1350 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1351 expectedFlags);
1352 }
1353
arthurhungb89ccb02020-12-30 16:19:01 +08001354 void consumeDragEvent(bool isExiting, float x, float y) {
1355 mInputReceiver->consumeDragEvent(isExiting, x, y);
1356 }
1357
Antonio Kantekf16f2832021-09-28 04:39:20 +00001358 void consumeTouchModeEvent(bool inTouchMode) {
1359 ASSERT_NE(mInputReceiver, nullptr)
1360 << "Cannot consume events from a window with no receiver";
1361 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1362 }
1363
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001364 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001365 if (mInputReceiver == nullptr) {
1366 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1367 return std::nullopt;
1368 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001369 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001370 }
1371
1372 void finishEvent(uint32_t sequenceNum) {
1373 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1374 mInputReceiver->finishEvent(sequenceNum);
1375 }
1376
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001377 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1378 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1379 mInputReceiver->sendTimeline(inputEventId, timeline);
1380 }
1381
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001382 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001383 if (mInputReceiver == nullptr) {
1384 return nullptr;
1385 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001386 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001387 }
1388
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001389 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001390 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001391 if (event == nullptr) {
1392 ADD_FAILURE() << "Consume failed : no event";
1393 return nullptr;
1394 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001395 if (event->getType() != InputEventType::MOTION) {
1396 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001397 return nullptr;
1398 }
1399 return static_cast<MotionEvent*>(event);
1400 }
1401
Arthur Hungb92218b2018-08-14 12:00:21 +08001402 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001403 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001404 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001405 return; // Can't receive events if the window does not have input channel
1406 }
1407 ASSERT_NE(nullptr, mInputReceiver)
1408 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001409 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001410 }
1411
chaviwaf87b3e2019-10-01 16:59:28 -07001412 sp<IBinder> getToken() { return mInfo.token; }
1413
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001414 const std::string& getName() { return mName; }
1415
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001416 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001417 mInfo.ownerPid = ownerPid;
1418 mInfo.ownerUid = ownerUid;
1419 }
1420
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001421 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001422
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001423 void destroyReceiver() { mInputReceiver = nullptr; }
1424
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001425 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1426
chaviwd1c23182019-12-20 18:44:56 -08001427private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001428 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001429 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001430 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001431 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001432 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001433};
1434
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001435std::atomic<int32_t> FakeWindowHandle::sId{1};
1436
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001437class FakeMonitorReceiver {
1438public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001439 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001440 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001441 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001442 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1443 }
1444
1445 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1446
1447 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1448 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1449 expectedFlags);
1450 }
1451
1452 std::optional<int32_t> receiveEvent() {
1453 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1454 }
1455
1456 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1457
1458 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1459 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1460 expectedDisplayId, expectedFlags);
1461 }
1462
1463 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1464 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1465 expectedDisplayId, expectedFlags);
1466 }
1467
1468 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1469 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1470 expectedDisplayId, expectedFlags);
1471 }
1472
1473 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1474 mInputReceiver->consumeMotionEvent(
1475 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1476 WithDisplayId(expectedDisplayId),
1477 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1478 }
1479
1480 void consumeMotionPointerDown(int32_t pointerIdx) {
1481 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1482 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1483 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1484 /*expectedFlags=*/0);
1485 }
1486
1487 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1488 mInputReceiver->consumeMotionEvent(matcher);
1489 }
1490
1491 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1492
1493 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1494
1495private:
1496 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1497};
1498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 int32_t displayId = ADISPLAY_ID_NONE,
1502 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001503 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001504 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001505 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001506 KeyEvent event;
1507 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1508
1509 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001510 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001511 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1512 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001513
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001514 if (!allowKeyRepeat) {
1515 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1516 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001517 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001519}
1520
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001521static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1522 InputEventInjectionResult result =
1523 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1524 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1525 if (result != InputEventInjectionResult::TIMED_OUT) {
1526 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1527 }
1528}
1529
1530static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001531 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001532 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001533}
1534
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001535// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1536// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1537// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001538static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1539 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001540 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001541 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001542 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001543}
1544
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001545static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001546 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001547 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001548}
1549
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001550static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001551 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001552 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001553 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001554 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001555 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1556 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001557}
1558
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001559static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001560 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1561 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001562 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001563 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1564 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001565 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001566 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001567 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001568 MotionEventBuilder motionBuilder =
1569 MotionEventBuilder(action, source)
1570 .displayId(displayId)
1571 .eventTime(eventTime)
1572 .rawXCursorPosition(cursorPosition.x)
1573 .rawYCursorPosition(cursorPosition.y)
1574 .pointer(
1575 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1576 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1577 motionBuilder.downTime(eventTime);
1578 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001579
1580 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001581 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1582 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001583}
1584
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001585static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1586 int32_t displayId,
1587 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001588 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001589}
1590
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001591static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1592 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001593 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001594 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001595}
1596
Jackal Guof9696682018-10-05 12:23:23 +08001597static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1598 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1599 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001600 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001601 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1602 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001603
1604 return args;
1605}
1606
Josep del Riob3981622023-04-18 15:49:45 +00001607static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1608 int32_t displayId = ADISPLAY_ID_NONE) {
1609 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1610 // Define a valid key event.
1611 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001612 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001613 currentTime);
1614
1615 return args;
1616}
1617
1618static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1619 int32_t displayId = ADISPLAY_ID_NONE) {
1620 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1621 // Define a valid key event.
1622 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001623 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001624 AMETA_NONE, currentTime);
1625
1626 return args;
1627}
1628
Prabir Pradhan678438e2023-04-13 19:32:51 +00001629[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1630 int32_t displayId,
1631 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001632 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001633 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1634 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1635 }
1636
chaviwd1c23182019-12-20 18:44:56 -08001637 PointerProperties pointerProperties[pointerCount];
1638 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001639
chaviwd1c23182019-12-20 18:44:56 -08001640 for (size_t i = 0; i < pointerCount; i++) {
1641 pointerProperties[i].clear();
1642 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001643 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001644
chaviwd1c23182019-12-20 18:44:56 -08001645 pointerCoords[i].clear();
1646 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1647 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1648 }
Jackal Guof9696682018-10-05 12:23:23 +08001649
1650 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1651 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001652 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001653 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1654 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001655 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001656 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001657 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001658 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001659
1660 return args;
1661}
1662
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001663static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1664 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1665}
1666
chaviwd1c23182019-12-20 18:44:56 -08001667static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1668 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1669}
1670
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001671static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1672 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001673 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001674}
1675
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001676} // namespace
1677
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001678/**
1679 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1680 * broken channel.
1681 */
1682TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1684 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001687
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001689
1690 // Window closes its channel, but the window remains.
1691 window->destroyReceiver();
1692 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1693}
1694
Arthur Hungb92218b2018-08-14 12:00:21 +08001695TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001697 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1698 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001699
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001700 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001704
1705 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001706 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001707}
1708
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001709TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1712 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001715 // Inject a MotionEvent to an unknown display.
1716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1719
1720 // Window should receive motion event.
1721 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1722}
1723
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001724/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001725 * Calling onWindowInfosChanged once should not cause any issues.
1726 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001727 * called twice.
1728 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001729TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001731 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1732 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001733 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001738 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001740
1741 // Window should receive motion event.
1742 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1743}
1744
1745/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001746 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001747 */
1748TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001750 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1751 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001752 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001754 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001757 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001758 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001760
1761 // Window should receive motion event.
1762 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1763}
1764
Arthur Hungb92218b2018-08-14 12:00:21 +08001765// The foreground window should receive the first touch down event.
1766TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001768 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001769 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001770 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001771 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001772
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001773 mDispatcher->onWindowInfosChanged(
1774 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001778
1779 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001780 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001781 windowSecond->assertNoEvents();
1782}
1783
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784/**
1785 * Two windows: A top window, and a wallpaper behind the window.
1786 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1787 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001788 * 1. foregroundWindow <-- dup touch to wallpaper
1789 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001790 */
1791TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1793 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001794 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001795 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001796 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001797 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001798 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001799
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001800 mDispatcher->onWindowInfosChanged(
1801 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001804 {100, 200}))
1805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1806
1807 // Both foreground window and its wallpaper should receive the touch down
1808 foregroundWindow->consumeMotionDown();
1809 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1810
1811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001812 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001813 ADISPLAY_ID_DEFAULT, {110, 200}))
1814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1815
1816 foregroundWindow->consumeMotionMove();
1817 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1818
1819 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001821 foregroundWindow->consumeMotionCancel();
1822 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1823 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1824}
1825
1826/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001827 * Two fingers down on the window, and lift off the first finger.
1828 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1829 * contains a single pointer.
1830 */
1831TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1833 sp<FakeWindowHandle> window =
1834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001837 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1839 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1840 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001841 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001842 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1843 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1844 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1845 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001846 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001847 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1848 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1849 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1850 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001851 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1852 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1853 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1854
1855 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001856 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001857 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1858 window->consumeMotionEvent(
1859 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1860}
1861
1862/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001863 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1864 * with the following differences:
1865 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1866 * clean up the connection.
1867 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1868 * Ensure that there's no crash in the dispatcher.
1869 */
1870TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1871 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1872 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001873 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001874 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001875 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001876 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001877 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001878
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001879 mDispatcher->onWindowInfosChanged(
1880 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001882 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001883 {100, 200}))
1884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1885
1886 // Both foreground window and its wallpaper should receive the touch down
1887 foregroundWindow->consumeMotionDown();
1888 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1889
1890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001891 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001892 ADISPLAY_ID_DEFAULT, {110, 200}))
1893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1894
1895 foregroundWindow->consumeMotionMove();
1896 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1897
1898 // Wallpaper closes its channel, but the window remains.
1899 wallpaperWindow->destroyReceiver();
1900 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1901
1902 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1903 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001904 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001905 foregroundWindow->consumeMotionCancel();
1906}
1907
Arthur Hungc539dbb2022-12-08 07:45:36 +00001908class ShouldSplitTouchFixture : public InputDispatcherTest,
1909 public ::testing::WithParamInterface<bool> {};
1910INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1911 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001912/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 * A single window that receives touch (on top), and a wallpaper window underneath it.
1914 * The top window gets a multitouch gesture.
1915 * Ensure that wallpaper gets the same gesture.
1916 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001917TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919 sp<FakeWindowHandle> foregroundWindow =
1920 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1921 foregroundWindow->setDupTouchToWallpaper(true);
1922 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001923
1924 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001925 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001926 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001927
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001928 mDispatcher->onWindowInfosChanged(
1929 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001930
1931 // Touch down on top window
1932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001933 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934 {100, 100}))
1935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1936
1937 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001938 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001939 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1940
1941 // Second finger down on the top window
1942 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001943 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001945 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1946 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947 .build();
1948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001949 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950 InputEventInjectionSync::WAIT_FOR_RESULT))
1951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1952
Harry Cutts33476232023-01-30 19:57:29 +00001953 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1954 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001956
1957 const MotionEvent secondFingerUpEvent =
1958 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1959 .displayId(ADISPLAY_ID_DEFAULT)
1960 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001961 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1962 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001963 .build();
1964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001965 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001966 InputEventInjectionSync::WAIT_FOR_RESULT))
1967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1968 foregroundWindow->consumeMotionPointerUp(0);
1969 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1970
1971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001972 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001973 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1974 AINPUT_SOURCE_TOUCHSCREEN)
1975 .displayId(ADISPLAY_ID_DEFAULT)
1976 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001977 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001978 .x(100)
1979 .y(100))
1980 .build(),
1981 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1983 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1984 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985}
1986
1987/**
1988 * Two windows: a window on the left and window on the right.
1989 * A third window, wallpaper, is behind both windows, and spans both top windows.
1990 * The first touch down goes to the left window. A second pointer touches down on the right window.
1991 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1992 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1993 * ACTION_POINTER_DOWN(1).
1994 */
1995TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1996 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1997 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001998 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002000 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002001
2002 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002003 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002005 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006
2007 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002008 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002010 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002011
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002012 mDispatcher->onWindowInfosChanged(
2013 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2014 {},
2015 0,
2016 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017
2018 // Touch down on left window
2019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002020 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 {100, 100}))
2022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2023
2024 // Both foreground window and its wallpaper should receive the touch down
2025 leftWindow->consumeMotionDown();
2026 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2027
2028 // Second finger down on the right window
2029 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002030 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002031 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002032 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2033 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002034 .build();
2035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002036 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037 InputEventInjectionSync::WAIT_FOR_RESULT))
2038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2039
2040 leftWindow->consumeMotionMove();
2041 // Since the touch is split, right window gets ACTION_DOWN
2042 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002043 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044 expectedWallpaperFlags);
2045
2046 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002047 mDispatcher->onWindowInfosChanged(
2048 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 leftWindow->consumeMotionCancel();
2050 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2051 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2052
2053 // The pointer that's still down on the right window moves, and goes to the right window only.
2054 // As far as the dispatcher's concerned though, both pointers are still present.
2055 const MotionEvent secondFingerMoveEvent =
2056 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2057 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002058 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2059 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002060 .build();
2061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002062 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002063 InputEventInjectionSync::WAIT_FOR_RESULT));
2064 rightWindow->consumeMotionMove();
2065
2066 leftWindow->assertNoEvents();
2067 rightWindow->assertNoEvents();
2068 wallpaperWindow->assertNoEvents();
2069}
2070
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071/**
2072 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2073 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2074 * The right window should receive ACTION_DOWN.
2075 */
2076TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002078 sp<FakeWindowHandle> leftWindow =
2079 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2080 leftWindow->setFrame(Rect(0, 0, 200, 200));
2081 leftWindow->setDupTouchToWallpaper(true);
2082 leftWindow->setSlippery(true);
2083
2084 sp<FakeWindowHandle> rightWindow =
2085 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2086 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002087
2088 sp<FakeWindowHandle> wallpaperWindow =
2089 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2090 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002091
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002092 mDispatcher->onWindowInfosChanged(
2093 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2094 {},
2095 0,
2096 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002097
Arthur Hungc539dbb2022-12-08 07:45:36 +00002098 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002100 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002101 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002103
2104 // Both foreground window and its wallpaper should receive the touch down
2105 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002106 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2107
Arthur Hungc539dbb2022-12-08 07:45:36 +00002108 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002110 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002111 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2113
Arthur Hungc539dbb2022-12-08 07:45:36 +00002114 leftWindow->consumeMotionCancel();
2115 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2116 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002117}
2118
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002119/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002120 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2121 * interactive, it might stop sending this flag.
2122 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2123 * to have a consistent input stream.
2124 *
2125 * Test procedure:
2126 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2127 * DOWN (new gesture).
2128 *
2129 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2130 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2131 *
2132 * We technically just need a single window here, but we are using two windows (spy on top and a
2133 * regular window below) to emulate the actual situation where it happens on the device.
2134 */
2135TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2136 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2137 sp<FakeWindowHandle> spyWindow =
2138 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2139 spyWindow->setFrame(Rect(0, 0, 200, 200));
2140 spyWindow->setTrustedOverlay(true);
2141 spyWindow->setSpy(true);
2142
2143 sp<FakeWindowHandle> window =
2144 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2145 window->setFrame(Rect(0, 0, 200, 200));
2146
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002147 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002148 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002149
2150 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002151 mDispatcher->notifyMotion(
2152 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2153 .deviceId(touchDeviceId)
2154 .policyFlags(DEFAULT_POLICY_FLAGS)
2155 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2156 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002157
Prabir Pradhan678438e2023-04-13 19:32:51 +00002158 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2159 .deviceId(touchDeviceId)
2160 .policyFlags(DEFAULT_POLICY_FLAGS)
2161 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2162 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2163 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002164 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2165 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2166 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2167 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2168
2169 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002170 mDispatcher->notifyMotion(
2171 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2172 .deviceId(touchDeviceId)
2173 .policyFlags(0)
2174 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2175 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2176 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002177 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2178 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2179
2180 // We don't need to reset the device to reproduce the issue, but the reset event typically
2181 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002182 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002183
2184 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002185 mDispatcher->notifyMotion(
2186 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2187 .deviceId(touchDeviceId)
2188 .policyFlags(DEFAULT_POLICY_FLAGS)
2189 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2190 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002191 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2192 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2193
2194 // No more events
2195 spyWindow->assertNoEvents();
2196 window->assertNoEvents();
2197}
2198
2199/**
Linnan Li907ae732023-09-05 17:14:21 +08002200 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2201 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2202 * interactive, it might stop sending this flag.
2203 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2204 * the consistency of the hover event in this case.
2205 *
2206 * Test procedure:
2207 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2208 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2209 *
2210 * We expect to receive two full streams of hover events.
2211 */
2212TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2214
2215 sp<FakeWindowHandle> window =
2216 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2217 window->setFrame(Rect(0, 0, 300, 300));
2218
2219 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2220
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(DEFAULT_POLICY_FLAGS)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2224 .build());
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2232
2233 // Send hover exit without the default policy flags.
2234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2235 .policyFlags(0)
2236 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2237 .build());
2238
2239 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2240
2241 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2242 // right event.
2243 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2244 .policyFlags(DEFAULT_POLICY_FLAGS)
2245 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2246 .build());
2247 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2248
2249 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2250 .policyFlags(DEFAULT_POLICY_FLAGS)
2251 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2252 .build());
2253 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2254
2255 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2256 .policyFlags(DEFAULT_POLICY_FLAGS)
2257 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2258 .build());
2259 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2260}
2261
2262/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002263 * Two windows: a window on the left and a window on the right.
2264 * Mouse is hovered from the right window into the left window.
2265 * Next, we tap on the left window, where the cursor was last seen.
2266 * The second tap is done onto the right window.
2267 * The mouse and tap are from two different devices.
2268 * We technically don't need to set the downtime / eventtime for these events, but setting these
2269 * explicitly helps during debugging.
2270 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2271 * In the buggy implementation, a tap on the right window would cause a crash.
2272 */
2273TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2275 sp<FakeWindowHandle> leftWindow =
2276 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2277 leftWindow->setFrame(Rect(0, 0, 200, 200));
2278
2279 sp<FakeWindowHandle> rightWindow =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2281 rightWindow->setFrame(Rect(200, 0, 400, 200));
2282
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002283 mDispatcher->onWindowInfosChanged(
2284 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002285 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2286 // stale.
2287 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2288 const int32_t mouseDeviceId = 6;
2289 const int32_t touchDeviceId = 4;
2290 // Move the cursor from right
2291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002292 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002293 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2294 AINPUT_SOURCE_MOUSE)
2295 .deviceId(mouseDeviceId)
2296 .downTime(baseTime + 10)
2297 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002298 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002299 .build()));
2300 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2301
2302 // .. to the left window
2303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002304 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002305 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2306 AINPUT_SOURCE_MOUSE)
2307 .deviceId(mouseDeviceId)
2308 .downTime(baseTime + 10)
2309 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002310 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002311 .build()));
2312 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2313 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2314 // Now tap the left window
2315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002316 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002317 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2318 AINPUT_SOURCE_TOUCHSCREEN)
2319 .deviceId(touchDeviceId)
2320 .downTime(baseTime + 40)
2321 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002322 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002323 .build()));
2324 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2325 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2326
2327 // release tap
2328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002329 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002330 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2331 AINPUT_SOURCE_TOUCHSCREEN)
2332 .deviceId(touchDeviceId)
2333 .downTime(baseTime + 40)
2334 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002335 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002336 .build()));
2337 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2338
2339 // Tap the window on the right
2340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002341 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002342 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2343 AINPUT_SOURCE_TOUCHSCREEN)
2344 .deviceId(touchDeviceId)
2345 .downTime(baseTime + 60)
2346 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002347 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002348 .build()));
2349 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2350
2351 // release tap
2352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002353 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002354 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2355 AINPUT_SOURCE_TOUCHSCREEN)
2356 .deviceId(touchDeviceId)
2357 .downTime(baseTime + 60)
2358 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002359 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002360 .build()));
2361 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2362
2363 // No more events
2364 leftWindow->assertNoEvents();
2365 rightWindow->assertNoEvents();
2366}
2367
2368/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002369 * Start hovering in a window. While this hover is still active, make another window appear on top.
2370 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2371 * While the top window is present, the hovering is stopped.
2372 * Later, hovering gets resumed again.
2373 * Ensure that new hover gesture is handled correctly.
2374 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2375 * to the window that's currently being hovered over.
2376 */
2377TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2379 sp<FakeWindowHandle> window =
2380 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2381 window->setFrame(Rect(0, 0, 200, 200));
2382
2383 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002384 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002385
2386 // Start hovering in the window
2387 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2388 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2389 .build());
2390 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2391
2392 // Now, an obscuring window appears!
2393 sp<FakeWindowHandle> obscuringWindow =
2394 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2395 ADISPLAY_ID_DEFAULT,
2396 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2397 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2398 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2399 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2400 obscuringWindow->setNoInputChannel(true);
2401 obscuringWindow->setFocusable(false);
2402 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002403 mDispatcher->onWindowInfosChanged(
2404 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002405
2406 // While this new obscuring window is present, the hovering is stopped
2407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2408 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2409 .build());
2410 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2411
2412 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002414
2415 // And a new hover gesture starts.
2416 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2417 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2418 .build());
2419 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2420}
2421
2422/**
2423 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2424 * the obscuring window.
2425 */
2426TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2428 sp<FakeWindowHandle> window =
2429 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2430 window->setFrame(Rect(0, 0, 200, 200));
2431
2432 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002433 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002434
2435 // Start hovering in the window
2436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2437 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2438 .build());
2439 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2440
2441 // Now, an obscuring window appears!
2442 sp<FakeWindowHandle> obscuringWindow =
2443 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2444 ADISPLAY_ID_DEFAULT,
2445 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2446 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2447 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2448 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2449 obscuringWindow->setNoInputChannel(true);
2450 obscuringWindow->setFocusable(false);
2451 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002452 mDispatcher->onWindowInfosChanged(
2453 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002454
2455 // While this new obscuring window is present, the hovering continues. The event can't go to the
2456 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2458 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2459 .build());
2460 obscuringWindow->assertNoEvents();
2461 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2462
2463 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002464 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002465
2466 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2467 // so it should generate a HOVER_ENTER
2468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2469 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2470 .build());
2471 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2472
2473 // Now the MOVE should be getting dispatched normally
2474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2475 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2476 .build());
2477 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2478}
2479
2480/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002481 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2482 * events are delivered to the window.
2483 */
2484TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2486 sp<FakeWindowHandle> window =
2487 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2488 window->setFrame(Rect(0, 0, 200, 200));
2489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2490
2491 // Start hovering in the window
2492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2493 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2494 .build());
2495 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2496
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2498 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2499 .build());
2500 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2501
2502 // Scroll with the mouse
2503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2504 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2505 .build());
2506 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2507}
2508
2509using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2510
2511/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002512 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2513 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002514 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002515TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2517 sp<FakeWindowHandle> window =
2518 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2519 window->setFrame(Rect(0, 0, 200, 200));
2520
2521 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2522
2523 constexpr int32_t touchDeviceId = 4;
2524 constexpr int32_t stylusDeviceId = 2;
2525
2526 // Stylus down
2527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2528 .deviceId(stylusDeviceId)
2529 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2530 .build());
2531 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2532
2533 // Touch down
2534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2535 .deviceId(touchDeviceId)
2536 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2537 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002538
2539 // Touch move
2540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2541 .deviceId(touchDeviceId)
2542 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2543 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002544 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002545
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002546 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2548 .deviceId(stylusDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2550 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2552 WithCoords(101, 111)));
2553
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002554 window->assertNoEvents();
2555}
2556
2557/**
2558 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002559 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002560 * Similar test as above, but with added SPY window.
2561 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002562TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2564 sp<FakeWindowHandle> window =
2565 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2566 sp<FakeWindowHandle> spyWindow =
2567 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2568 spyWindow->setFrame(Rect(0, 0, 200, 200));
2569 spyWindow->setTrustedOverlay(true);
2570 spyWindow->setSpy(true);
2571 window->setFrame(Rect(0, 0, 200, 200));
2572
2573 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2574
2575 constexpr int32_t touchDeviceId = 4;
2576 constexpr int32_t stylusDeviceId = 2;
2577
2578 // Stylus down
2579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2580 .deviceId(stylusDeviceId)
2581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2582 .build());
2583 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2584 spyWindow->consumeMotionEvent(
2585 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2586
2587 // Touch down
2588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2589 .deviceId(touchDeviceId)
2590 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2591 .build());
2592
2593 // Touch move
2594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2595 .deviceId(touchDeviceId)
2596 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2597 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002598
2599 // Touch is ignored because stylus is already down
2600
2601 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2603 .deviceId(stylusDeviceId)
2604 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2605 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002606 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2607 WithCoords(101, 111)));
2608 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2609 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002610
2611 window->assertNoEvents();
2612 spyWindow->assertNoEvents();
2613}
2614
2615/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002616 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2617 * touch is not dropped, because stylus hover should be ignored.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002618 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002619TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2621 sp<FakeWindowHandle> window =
2622 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2623 window->setFrame(Rect(0, 0, 200, 200));
2624
2625 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2626
2627 constexpr int32_t touchDeviceId = 4;
2628 constexpr int32_t stylusDeviceId = 2;
2629
2630 // Stylus down on the window
2631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2632 .deviceId(stylusDeviceId)
2633 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2634 .build());
2635 window->consumeMotionEvent(
2636 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2637
2638 // Touch down on window
2639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2642 .build());
2643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2644 .deviceId(touchDeviceId)
2645 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2646 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002647
2648 // Stylus hover is canceled because touch is down
2649 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT),
2650 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2651 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2652 WithCoords(140, 145)));
2653 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2654 WithCoords(141, 146)));
2655
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002656 // Subsequent stylus movements are ignored
2657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2658 .deviceId(stylusDeviceId)
2659 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2660 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002661
2662 // but subsequent touches continue to be delivered
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2664 .deviceId(touchDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2666 .build());
2667 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2668 WithCoords(142, 147)));
2669}
2670
2671/**
2672 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2673 * Ensure that touch is not canceled, because stylus hover should be dropped.
2674 */
2675TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2676 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2677 sp<FakeWindowHandle> window =
2678 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2679 window->setFrame(Rect(0, 0, 200, 200));
2680
2681 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2682
2683 constexpr int32_t touchDeviceId = 4;
2684 constexpr int32_t stylusDeviceId = 2;
2685
2686 // Touch down on window
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2690 .build());
2691 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2692 .deviceId(touchDeviceId)
2693 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2694 .build());
2695 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2696 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2697
2698 // Stylus hover on the window
2699 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2700 .deviceId(stylusDeviceId)
2701 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2702 .build());
2703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2704 .deviceId(stylusDeviceId)
2705 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2706 .build());
2707 // Stylus hover movement is dropped
2708
2709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2710 .deviceId(touchDeviceId)
2711 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2712 .build());
2713 // Subsequent touch movements are delivered correctly
2714 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2715 WithCoords(142, 147)));
2716}
2717
2718/**
2719 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2720 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2721 * become active.
2722 */
2723TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2725 sp<FakeWindowHandle> window =
2726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2727 window->setFrame(Rect(0, 0, 200, 200));
2728
2729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2730
2731 constexpr int32_t stylusDeviceId1 = 3;
2732 constexpr int32_t stylusDeviceId2 = 5;
2733
2734 // Touch down on window
2735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2736 .deviceId(stylusDeviceId1)
2737 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2738 .build());
2739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2740 .deviceId(stylusDeviceId1)
2741 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2742 .build());
2743 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2744 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2745
2746 // Second stylus down
2747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2748 .deviceId(stylusDeviceId2)
2749 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2750 .build());
2751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2752 .deviceId(stylusDeviceId2)
2753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2754 .build());
2755
2756 // First stylus is canceled, second one takes over.
2757 window->consumeMotionEvent(
2758 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2759 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2760 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2761
2762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2763 .deviceId(stylusDeviceId1)
2764 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2765 .build());
2766 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002767 window->assertNoEvents();
2768}
2769
2770/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002771 * One window. Touch down on the window. Then, stylus down on the window from another device.
2772 * Ensure that is canceled, because stylus down should be preferred over touch.
2773 */
2774TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2776 sp<FakeWindowHandle> window =
2777 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2778 window->setFrame(Rect(0, 0, 200, 200));
2779
2780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2781
2782 constexpr int32_t touchDeviceId = 4;
2783 constexpr int32_t stylusDeviceId = 2;
2784
2785 // Touch down on window
2786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2787 .deviceId(touchDeviceId)
2788 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2789 .build());
2790 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2791 .deviceId(touchDeviceId)
2792 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2793 .build());
2794 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2795 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2796
2797 // Stylus down on the window
2798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2799 .deviceId(stylusDeviceId)
2800 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2801 .build());
2802 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2803 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2804
2805 // Subsequent stylus movements are delivered correctly
2806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2807 .deviceId(stylusDeviceId)
2808 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2809 .build());
2810 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2811 WithCoords(101, 111)));
2812}
2813
2814/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815 * Two windows: a window on the left and a window on the right.
2816 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2817 * down. Then, on the left window, also place second touch pointer down.
2818 * This test tries to reproduce a crash.
2819 * In the buggy implementation, second pointer down on the left window would cause a crash.
2820 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002821TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2823 sp<FakeWindowHandle> leftWindow =
2824 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2825 leftWindow->setFrame(Rect(0, 0, 200, 200));
2826
2827 sp<FakeWindowHandle> rightWindow =
2828 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2829 rightWindow->setFrame(Rect(200, 0, 400, 200));
2830
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002831 mDispatcher->onWindowInfosChanged(
2832 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002833
2834 const int32_t touchDeviceId = 4;
2835 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836
2837 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2839 .deviceId(mouseDeviceId)
2840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2841 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002842 leftWindow->consumeMotionEvent(
2843 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2844
2845 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2847 .deviceId(mouseDeviceId)
2848 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2849 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2850 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002851
2852 leftWindow->consumeMotionEvent(
2853 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2854 leftWindow->consumeMotionEvent(
2855 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2856
Prabir Pradhan678438e2023-04-13 19:32:51 +00002857 mDispatcher->notifyMotion(
2858 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2859 .deviceId(mouseDeviceId)
2860 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2861 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2863 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002864 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2865
2866 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2868 .deviceId(touchDeviceId)
2869 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2870 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002871 leftWindow->assertNoEvents();
2872
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2874
2875 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2879 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2880 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002881 // Since this is now a new splittable pointer going down on the left window, and it's coming
2882 // from a different device, the current gesture in the left window (pointer down) should first
2883 // be canceled.
2884 leftWindow->consumeMotionEvent(
2885 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002886 leftWindow->consumeMotionEvent(
2887 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2888 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2889 // current implementation.
2890 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2891 rightWindow->consumeMotionEvent(
2892 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2893
2894 leftWindow->assertNoEvents();
2895 rightWindow->assertNoEvents();
2896}
2897
2898/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002899 * Two windows: a window on the left and a window on the right.
2900 * Mouse is hovered on the left window and stylus is hovered on the right window.
2901 */
2902TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2904 sp<FakeWindowHandle> leftWindow =
2905 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2906 leftWindow->setFrame(Rect(0, 0, 200, 200));
2907
2908 sp<FakeWindowHandle> rightWindow =
2909 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2910 rightWindow->setFrame(Rect(200, 0, 400, 200));
2911
2912 mDispatcher->onWindowInfosChanged(
2913 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2914
2915 const int32_t stylusDeviceId = 3;
2916 const int32_t mouseDeviceId = 6;
2917
2918 // Start hovering over the left window
2919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2920 .deviceId(mouseDeviceId)
2921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2922 .build());
2923 leftWindow->consumeMotionEvent(
2924 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2925
2926 // Stylus hovered on right window
2927 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2928 .deviceId(stylusDeviceId)
2929 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2930 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931 rightWindow->consumeMotionEvent(
2932 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2933
2934 // Subsequent HOVER_MOVE events are dispatched correctly.
2935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2936 .deviceId(mouseDeviceId)
2937 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2938 .build());
2939 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002940 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002941
2942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2943 .deviceId(stylusDeviceId)
2944 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2945 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002946 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002947 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002948
2949 leftWindow->assertNoEvents();
2950 rightWindow->assertNoEvents();
2951}
2952
2953/**
2954 * Three windows: a window on the left and a window on the right.
2955 * And a spy window that's positioned above all of them.
2956 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2957 * Check the stream that's received by the spy.
2958 */
2959TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2960 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2961
2962 sp<FakeWindowHandle> spyWindow =
2963 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2964 spyWindow->setFrame(Rect(0, 0, 400, 400));
2965 spyWindow->setTrustedOverlay(true);
2966 spyWindow->setSpy(true);
2967
2968 sp<FakeWindowHandle> leftWindow =
2969 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2970 leftWindow->setFrame(Rect(0, 0, 200, 200));
2971
2972 sp<FakeWindowHandle> rightWindow =
2973 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2974
2975 rightWindow->setFrame(Rect(200, 0, 400, 200));
2976
2977 mDispatcher->onWindowInfosChanged(
2978 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2979
2980 const int32_t stylusDeviceId = 1;
2981 const int32_t touchDeviceId = 2;
2982
2983 // Stylus down on the left window
2984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2985 .deviceId(stylusDeviceId)
2986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2987 .build());
2988 leftWindow->consumeMotionEvent(
2989 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2990 spyWindow->consumeMotionEvent(
2991 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2992
2993 // Touch down on the right window
2994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2995 .deviceId(touchDeviceId)
2996 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2997 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002998 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002999 rightWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003002 // Spy window does not receive touch events, because stylus events take precedence, and it
3003 // already has an active stylus gesture.
3004
3005 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3007 .deviceId(stylusDeviceId)
3008 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3009 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003010 leftWindow->consumeMotionEvent(
3011 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3012 spyWindow->consumeMotionEvent(
3013 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003014
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003015 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003016 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3017 .deviceId(touchDeviceId)
3018 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3019 .build());
3020 rightWindow->consumeMotionEvent(
3021 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003022
3023 spyWindow->assertNoEvents();
3024 leftWindow->assertNoEvents();
3025 rightWindow->assertNoEvents();
3026}
3027
3028/**
3029 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3030 * both.
3031 * Check hover in left window and touch down in the right window.
3032 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003033 * At the same time, left and right should be getting independent streams of hovering and touch,
3034 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003035 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003036TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlockedByTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3038
3039 sp<FakeWindowHandle> spyWindow =
3040 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3041 spyWindow->setFrame(Rect(0, 0, 400, 400));
3042 spyWindow->setTrustedOverlay(true);
3043 spyWindow->setSpy(true);
3044
3045 sp<FakeWindowHandle> leftWindow =
3046 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3047 leftWindow->setFrame(Rect(0, 0, 200, 200));
3048
3049 sp<FakeWindowHandle> rightWindow =
3050 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3051 rightWindow->setFrame(Rect(200, 0, 400, 200));
3052
3053 mDispatcher->onWindowInfosChanged(
3054 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3055
3056 const int32_t stylusDeviceId = 1;
3057 const int32_t touchDeviceId = 2;
3058
3059 // Stylus hover on the left window
3060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3061 .deviceId(stylusDeviceId)
3062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3063 .build());
3064 leftWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3066 spyWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3068
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003069 // Touch down on the right window. Spy doesn't receive this touch because it already has
3070 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3072 .deviceId(touchDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3074 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003075 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076 spyWindow->consumeMotionEvent(
3077 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3078 spyWindow->consumeMotionEvent(
3079 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3080 rightWindow->consumeMotionEvent(
3081 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3082
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003083 // Stylus movements continue. They should be delivered to the left window only.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003084 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3085 .deviceId(stylusDeviceId)
3086 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3087 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003088 leftWindow->consumeMotionEvent(
3089 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090
3091 // Touch movements continue. They should be delivered to the right window and to the spy
3092 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3093 .deviceId(touchDeviceId)
3094 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3095 .build());
3096 spyWindow->consumeMotionEvent(
3097 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3098 rightWindow->consumeMotionEvent(
3099 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3100
3101 spyWindow->assertNoEvents();
3102 leftWindow->assertNoEvents();
3103 rightWindow->assertNoEvents();
3104}
3105
3106/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003107 * On a single window, use two different devices: mouse and touch.
3108 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3109 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3110 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3111 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3112 * represent a new gesture.
3113 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003114TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3116 sp<FakeWindowHandle> window =
3117 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3118 window->setFrame(Rect(0, 0, 400, 400));
3119
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003120 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003121
3122 const int32_t touchDeviceId = 4;
3123 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003125 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003126 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3127 .deviceId(touchDeviceId)
3128 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3129 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003130 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3132 .deviceId(touchDeviceId)
3133 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3134 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003137 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, 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 Vishniakouf372b812023-02-14 18:06:51 -08003142 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3143 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3144 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3145
3146 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3148 .deviceId(mouseDeviceId)
3149 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3150 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3151 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003152
3153 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003154 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3156
Prabir Pradhan678438e2023-04-13 19:32:51 +00003157 mDispatcher->notifyMotion(
3158 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3159 .deviceId(mouseDeviceId)
3160 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3161 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3162 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3163 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003164 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3165
3166 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003167 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3168 .deviceId(touchDeviceId)
3169 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3170 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3171 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003172 // Since we already canceled this touch gesture, it will be ignored until a completely new
3173 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3174 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3175 // However, mouse movements should continue to work.
3176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3177 .deviceId(mouseDeviceId)
3178 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3179 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3180 .build());
3181 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3182
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003183 window->assertNoEvents();
3184}
3185
3186/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003187 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3188 * the injected event.
3189 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003190TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3192 sp<FakeWindowHandle> window =
3193 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3194 window->setFrame(Rect(0, 0, 400, 400));
3195
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003196 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003197
3198 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003199 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3200 // completion.
3201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003202 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003203 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3204 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003205 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003206 .build()));
3207 window->consumeMotionEvent(
3208 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3209
3210 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3211 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3213 .deviceId(touchDeviceId)
3214 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3215 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003216
3217 window->consumeMotionEvent(
3218 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3220}
3221
3222/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003223 * This test is similar to the test above, but the sequence of injected events is different.
3224 *
3225 * Two windows: a window on the left and a window on the right.
3226 * Mouse is hovered over the left window.
3227 * Next, we tap on the left window, where the cursor was last seen.
3228 *
3229 * After that, we inject one finger down onto the right window, and then a second finger down onto
3230 * the left window.
3231 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3232 * window (first), and then another on the left window (second).
3233 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3234 * In the buggy implementation, second finger down on the left window would cause a crash.
3235 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003236TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3238 sp<FakeWindowHandle> leftWindow =
3239 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3240 leftWindow->setFrame(Rect(0, 0, 200, 200));
3241
3242 sp<FakeWindowHandle> rightWindow =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3244 rightWindow->setFrame(Rect(200, 0, 400, 200));
3245
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003246 mDispatcher->onWindowInfosChanged(
3247 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248
3249 const int32_t mouseDeviceId = 6;
3250 const int32_t touchDeviceId = 4;
3251 // Hover over the left window. Keep the cursor there.
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_HOVER_ENTER,
3255 AINPUT_SOURCE_MOUSE)
3256 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 .build()));
3259 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3260
3261 // Tap on 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(AMOTION_EVENT_ACTION_DOWN,
3265 AINPUT_SOURCE_TOUCHSCREEN)
3266 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003267 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 .build()));
3269
3270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003272 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3273 AINPUT_SOURCE_TOUCHSCREEN)
3274 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003275 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003276 .build()));
3277 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3278 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3279 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3280
3281 // First finger down on right window
3282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003283 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003284 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3285 AINPUT_SOURCE_TOUCHSCREEN)
3286 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003287 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003288 .build()));
3289 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3290
3291 // Second finger down on the left window
3292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003293 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003294 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3295 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003296 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3297 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003298 .build()));
3299 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3300 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3301
3302 // No more events
3303 leftWindow->assertNoEvents();
3304 rightWindow->assertNoEvents();
3305}
3306
3307/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003308 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3309 * While the touch is down, new hover events from the stylus device should be ignored. After the
3310 * touch is gone, stylus hovering should start working again.
3311 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003312TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDroppedWhenTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3314 sp<FakeWindowHandle> window =
3315 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3316 window->setFrame(Rect(0, 0, 200, 200));
3317
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003318 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319
3320 const int32_t stylusDeviceId = 5;
3321 const int32_t touchDeviceId = 4;
3322 // Start hovering with stylus
3323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003324 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003325 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003326 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003327 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003328 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003329 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330
3331 // Finger down on the window
3332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003333 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003334 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003336 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003338 // The touch device should cause hover to stop!
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003339 window->consumeMotionEvent(
3340 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3341 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003342
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003343 // Continue hovering with stylus.
3344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3347 AINPUT_SOURCE_STYLUS)
3348 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003349 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003350 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003351 // Hovers are now ignored
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003352
3353 // Lift up the finger
3354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003356 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3357 AINPUT_SOURCE_TOUCHSCREEN)
3358 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003360 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003361 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003362
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003364 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003365 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3366 AINPUT_SOURCE_STYLUS)
3367 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003368 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003369 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003370 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3371 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003372 window->assertNoEvents();
3373}
3374
3375/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003376 * A spy window above a window with no input channel.
3377 * Start hovering with a stylus device, and then tap with it.
3378 * Ensure spy window receives the entire sequence.
3379 */
3380TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3382 sp<FakeWindowHandle> spyWindow =
3383 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3384 spyWindow->setFrame(Rect(0, 0, 200, 200));
3385 spyWindow->setTrustedOverlay(true);
3386 spyWindow->setSpy(true);
3387 sp<FakeWindowHandle> window =
3388 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3389 window->setNoInputChannel(true);
3390 window->setFrame(Rect(0, 0, 200, 200));
3391
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003392 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003393
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003394 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3396 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3397 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003398 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3399 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003403 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3404
3405 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003406 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3407 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3408 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003409 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3410
3411 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3413 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3414 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003415 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3416
3417 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3419 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3420 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003421 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3422 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3425 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003426 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3427
3428 // No more events
3429 spyWindow->assertNoEvents();
3430 window->assertNoEvents();
3431}
3432
3433/**
3434 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3435 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3436 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3437 * While the mouse is down, new move events from the touch device should be ignored.
3438 */
3439TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3441 sp<FakeWindowHandle> spyWindow =
3442 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3443 spyWindow->setFrame(Rect(0, 0, 200, 200));
3444 spyWindow->setTrustedOverlay(true);
3445 spyWindow->setSpy(true);
3446 sp<FakeWindowHandle> window =
3447 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3448 window->setFrame(Rect(0, 0, 200, 200));
3449
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003450 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003451
3452 const int32_t mouseDeviceId = 7;
3453 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003454
3455 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3457 .deviceId(mouseDeviceId)
3458 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3459 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003460 spyWindow->consumeMotionEvent(
3461 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3462 window->consumeMotionEvent(
3463 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3464
3465 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3467 .deviceId(touchDeviceId)
3468 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3469 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003470 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3471 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3472 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3473 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3474
Prabir Pradhan678438e2023-04-13 19:32:51 +00003475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3476 .deviceId(touchDeviceId)
3477 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3478 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003479 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3480 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3481
3482 // Pilfer the stream
3483 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3484 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3485
Prabir Pradhan678438e2023-04-13 19:32:51 +00003486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3487 .deviceId(touchDeviceId)
3488 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3489 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003490 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3491
3492 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3494 .deviceId(mouseDeviceId)
3495 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3496 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3497 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003498
3499 spyWindow->consumeMotionEvent(
3500 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3501 spyWindow->consumeMotionEvent(
3502 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3503 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3504
Prabir Pradhan678438e2023-04-13 19:32:51 +00003505 mDispatcher->notifyMotion(
3506 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3507 .deviceId(mouseDeviceId)
3508 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3509 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3510 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3511 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003512 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3513 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3514
3515 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3517 .deviceId(mouseDeviceId)
3518 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3519 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3522 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3523
3524 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3526 .deviceId(touchDeviceId)
3527 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3528 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003529
3530 // No more events
3531 spyWindow->assertNoEvents();
3532 window->assertNoEvents();
3533}
3534
3535/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003536 * On the display, have a single window, and also an area where there's no window.
3537 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3538 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3539 */
3540TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3542 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003544
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003545 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003546
3547 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003548 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003549
3550 mDispatcher->waitForIdle();
3551 window->assertNoEvents();
3552
3553 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003554 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003555 mDispatcher->waitForIdle();
3556 window->consumeMotionDown();
3557}
3558
3559/**
3560 * Same test as above, but instead of touching the empty space, the first touch goes to
3561 * non-touchable window.
3562 */
3563TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3565 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003566 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003567 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3568 window1->setTouchable(false);
3569 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003570 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003571 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3572
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003573 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003574
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003575 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003576 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003577
3578 mDispatcher->waitForIdle();
3579 window1->assertNoEvents();
3580 window2->assertNoEvents();
3581
3582 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003583 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003584 mDispatcher->waitForIdle();
3585 window2->consumeMotionDown();
3586}
3587
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003588/**
3589 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3590 * to the event time of the first ACTION_DOWN sent to the particular window.
3591 */
3592TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3594 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003595 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003596 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3597 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003598 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003599 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3600
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003601 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003603 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003604 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003605
3606 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003607
3608 MotionEvent* motionEvent1 = window1->consumeMotion();
3609 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003610 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003611 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3612 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003613
3614 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003615 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003616 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003617 MotionEvent* motionEvent2 = window2->consumeMotion();
3618 ASSERT_NE(motionEvent2, nullptr);
3619 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003620 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003621 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622
3623 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003624 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003625 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003626 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003627
3628 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003629 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003630 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003631 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003632
3633 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3634 window1->consumeMotionMove();
3635 window1->assertNoEvents();
3636
3637 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 mDispatcher->notifyMotion(
3639 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003640 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003641 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003642
Prabir Pradhan678438e2023-04-13 19:32:51 +00003643 mDispatcher->notifyMotion(
3644 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003645 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003646 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003647}
3648
Garfield Tandf26e862020-07-01 20:18:19 -07003649TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003651 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003652 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003653 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003654 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003655 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003656 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003657
3658 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3659
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003660 mDispatcher->onWindowInfosChanged(
3661 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003662
3663 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003665 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003666 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3667 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003668 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003669 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003670 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003671
3672 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003674 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003675 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3676 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003677 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003678 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003679 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3680 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003681
3682 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003684 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003685 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3686 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003687 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003688 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003689 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3690 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003691
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003693 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003694 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3695 AINPUT_SOURCE_MOUSE)
3696 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3697 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003698 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003699 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003700 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003701
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003703 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003704 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3705 AINPUT_SOURCE_MOUSE)
3706 .buttonState(0)
3707 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003708 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003709 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003710 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003713 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003714 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3715 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003716 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003717 .build()));
3718 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3719
3720 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003722 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003723 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3724 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003725 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003726 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003727 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003728
3729 // No more events
3730 windowLeft->assertNoEvents();
3731 windowRight->assertNoEvents();
3732}
3733
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003734/**
3735 * Put two fingers down (and don't release them) and click the mouse button.
3736 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3737 * currently active gesture should be canceled, and the new one should proceed.
3738 */
3739TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3740 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3741 sp<FakeWindowHandle> window =
3742 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3743 window->setFrame(Rect(0, 0, 600, 800));
3744
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003745 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003746
3747 const int32_t touchDeviceId = 4;
3748 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003749
3750 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3752 .deviceId(touchDeviceId)
3753 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3754 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003755
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3757 .deviceId(touchDeviceId)
3758 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3759 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003761 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3762 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3763
3764 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3766 .deviceId(mouseDeviceId)
3767 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3768 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3769 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003770 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3771 WithPointerCount(2u)));
3772 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3773
Prabir Pradhan678438e2023-04-13 19:32:51 +00003774 mDispatcher->notifyMotion(
3775 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3776 .deviceId(mouseDeviceId)
3777 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3778 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3779 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3780 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003781 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3782
3783 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3784 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3786 .deviceId(touchDeviceId)
3787 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3788 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3789 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003790 window->assertNoEvents();
3791}
3792
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003793TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3795
3796 sp<FakeWindowHandle> spyWindow =
3797 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3798 spyWindow->setFrame(Rect(0, 0, 600, 800));
3799 spyWindow->setTrustedOverlay(true);
3800 spyWindow->setSpy(true);
3801 sp<FakeWindowHandle> window =
3802 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3803 window->setFrame(Rect(0, 0, 600, 800));
3804
3805 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003806 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003807
3808 // Send mouse cursor to the window
3809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003810 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003811 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3812 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003813 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003814 .build()));
3815
3816 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3817 WithSource(AINPUT_SOURCE_MOUSE)));
3818 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3819 WithSource(AINPUT_SOURCE_MOUSE)));
3820
3821 window->assertNoEvents();
3822 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003823}
3824
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003825TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3826 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3827
3828 sp<FakeWindowHandle> spyWindow =
3829 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3830 spyWindow->setFrame(Rect(0, 0, 600, 800));
3831 spyWindow->setTrustedOverlay(true);
3832 spyWindow->setSpy(true);
3833 sp<FakeWindowHandle> window =
3834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3835 window->setFrame(Rect(0, 0, 600, 800));
3836
3837 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003838 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003839
3840 // Send mouse cursor to the window
3841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003842 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003843 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3844 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003846 .build()));
3847
3848 // Move mouse cursor
3849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003850 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003851 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3852 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003853 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003854 .build()));
3855
3856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3857 WithSource(AINPUT_SOURCE_MOUSE)));
3858 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3859 WithSource(AINPUT_SOURCE_MOUSE)));
3860 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3861 WithSource(AINPUT_SOURCE_MOUSE)));
3862 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3863 WithSource(AINPUT_SOURCE_MOUSE)));
3864 // Touch down on the window
3865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003866 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003867 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3868 AINPUT_SOURCE_TOUCHSCREEN)
3869 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003870 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003871 .build()));
3872 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3873 WithSource(AINPUT_SOURCE_MOUSE)));
3874 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3875 WithSource(AINPUT_SOURCE_MOUSE)));
3876 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3877 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3878 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3879 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3880
3881 // pilfer the motion, retaining the gesture on the spy window.
3882 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3883 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3884 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3885
3886 // Touch UP on the window
3887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003889 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3890 AINPUT_SOURCE_TOUCHSCREEN)
3891 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003892 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003893 .build()));
3894 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3895 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3896
3897 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3898 // to send a new gesture. It should again go to both windows (spy and the window below), just
3899 // like the first gesture did, before pilfering. The window configuration has not changed.
3900
3901 // One more tap - DOWN
3902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003903 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003904 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3905 AINPUT_SOURCE_TOUCHSCREEN)
3906 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003908 .build()));
3909 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3910 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3911 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3912 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3913
3914 // Touch UP on the window
3915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003916 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003917 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3918 AINPUT_SOURCE_TOUCHSCREEN)
3919 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003920 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003921 .build()));
3922 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3923 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3924 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3925 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3926
3927 window->assertNoEvents();
3928 spyWindow->assertNoEvents();
3929}
3930
Garfield Tandf26e862020-07-01 20:18:19 -07003931// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3932// directly in this test.
3933TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003935 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003936 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003937 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003938
3939 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3940
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003942
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003944 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003945 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3946 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003947 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003948 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003949 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003950 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003952 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003953 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3954 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003955 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003956 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003957 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3958 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003959
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003961 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003962 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3963 AINPUT_SOURCE_MOUSE)
3964 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3965 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003967 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003968 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003969
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003971 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003972 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3973 AINPUT_SOURCE_MOUSE)
3974 .buttonState(0)
3975 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003976 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003977 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003978 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003979
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003981 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003982 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3983 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003984 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003985 .build()));
3986 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3987
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003988 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3989 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3990 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003991 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003992 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3993 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003994 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003995 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003996 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003997}
3998
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003999/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004000 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4001 * is generated.
4002 */
4003TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4005 sp<FakeWindowHandle> window =
4006 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4007 window->setFrame(Rect(0, 0, 1200, 800));
4008
4009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4010
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004011 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004012
4013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004014 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004015 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4016 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004017 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004018 .build()));
4019 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4020
4021 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004022 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004023 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4024}
4025
4026/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004027 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4028 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004029TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4030 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4031 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4033 sp<FakeWindowHandle> window =
4034 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4035 window->setFrame(Rect(0, 0, 1200, 800));
4036
4037 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4038
4039 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4040
4041 MotionEventBuilder hoverEnterBuilder =
4042 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4044 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4046 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4048 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4049 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4050 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4051}
4052
4053/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004054 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4055 */
4056TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4057 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4058 sp<FakeWindowHandle> window =
4059 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4060 window->setFrame(Rect(0, 0, 100, 100));
4061
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004063
4064 const int32_t mouseDeviceId = 7;
4065 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004066
4067 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4069 .deviceId(mouseDeviceId)
4070 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4071 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004072 window->consumeMotionEvent(
4073 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4074
4075 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4077 .deviceId(touchDeviceId)
4078 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4079 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004080
4081 window->consumeMotionEvent(
4082 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4083 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4084}
4085
4086/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004087 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004088 * The tap causes a HOVER_EXIT event to be generated because the current event
4089 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004090 */
4091TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4093 sp<FakeWindowHandle> window =
4094 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4095 window->setFrame(Rect(0, 0, 100, 100));
4096
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4099 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4100 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004101 ASSERT_NO_FATAL_FAILURE(
4102 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4103 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004104
4105 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4107 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4108 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004109 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004110 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4111 WithSource(AINPUT_SOURCE_MOUSE))));
4112
4113 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004114 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4115 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4116
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4118 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4119 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004120 ASSERT_NO_FATAL_FAILURE(
4121 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4122 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4123}
4124
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004125TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4127 sp<FakeWindowHandle> windowDefaultDisplay =
4128 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4129 ADISPLAY_ID_DEFAULT);
4130 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4131 sp<FakeWindowHandle> windowSecondDisplay =
4132 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4133 SECOND_DISPLAY_ID);
4134 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4135
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004136 mDispatcher->onWindowInfosChanged(
4137 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004138
4139 // Set cursor position in window in default display and check that hover enter and move
4140 // events are generated.
4141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004142 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004143 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4144 AINPUT_SOURCE_MOUSE)
4145 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004146 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004147 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004148 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004149
4150 // Remove all windows in secondary display and check that no event happens on window in
4151 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004152 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4153
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004154 windowDefaultDisplay->assertNoEvents();
4155
4156 // Move cursor position in window in default display and check that only hover move
4157 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004158 mDispatcher->onWindowInfosChanged(
4159 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004161 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004162 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4163 AINPUT_SOURCE_MOUSE)
4164 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004166 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004167 windowDefaultDisplay->consumeMotionEvent(
4168 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4169 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004170 windowDefaultDisplay->assertNoEvents();
4171}
4172
Garfield Tan00f511d2019-06-12 16:55:40 -07004173TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004175
4176 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004177 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004178 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004179 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004180 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004181 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004182
4183 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4184
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004185 mDispatcher->onWindowInfosChanged(
4186 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004187
4188 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4189 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004191 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004192 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004193 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004194 windowRight->assertNoEvents();
4195}
4196
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004197TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004199 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4200 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004201 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004202
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004203 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004204 setFocusedWindow(window);
4205
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004206 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004207
Prabir Pradhan678438e2023-04-13 19:32:51 +00004208 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004209
4210 // Window should receive key down event.
4211 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4212
4213 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4214 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004215 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004216 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004217 AKEY_EVENT_FLAG_CANCELED);
4218}
4219
4220TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004222 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4223 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004224
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004225 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004226
Prabir Pradhan678438e2023-04-13 19:32:51 +00004227 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4228 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004229
4230 // Window should receive motion down event.
4231 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4232
4233 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4234 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004235 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004236 window->consumeMotionEvent(
4237 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004238}
4239
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004240TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4242 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4243 "Fake Window", ADISPLAY_ID_DEFAULT);
4244
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004246
4247 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4248 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4249 .build());
4250
4251 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4252
4253 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4254 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4255 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4256
4257 // After the device has been reset, a new hovering stream can be sent to the window
4258 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4259 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4260 .build());
4261 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4262}
4263
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004264TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004266 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4267 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004268 window->setFocusable(true);
4269
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004270 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271 setFocusedWindow(window);
4272
4273 window->consumeFocusEvent(true);
4274
Prabir Pradhan678438e2023-04-13 19:32:51 +00004275 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004276 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4277 const nsecs_t injectTime = keyArgs.eventTime;
4278 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004279 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004280 // The dispatching time should be always greater than or equal to intercept key timeout.
4281 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4282 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4283 std::chrono::nanoseconds(interceptKeyTimeout).count());
4284}
4285
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004286/**
4287 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4288 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004289TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4290 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004291 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4292 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004293 window->setFocusable(true);
4294
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004295 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004296 setFocusedWindow(window);
4297
4298 window->consumeFocusEvent(true);
4299
Prabir Pradhan678438e2023-04-13 19:32:51 +00004300 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004301 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004302
4303 // Set a value that's significantly larger than the default consumption timeout. If the
4304 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4305 mFakePolicy->setInterceptKeyTimeout(600ms);
4306 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4307 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004308 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4309}
4310
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004311/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004312 * Two windows. First is a regular window. Second does not overlap with the first, and has
4313 * WATCH_OUTSIDE_TOUCH.
4314 * Both windows are owned by the same UID.
4315 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4316 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4317 */
4318TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004320 sp<FakeWindowHandle> window =
4321 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004322 window->setFrame(Rect{0, 0, 100, 100});
4323
4324 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004325 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004326 ADISPLAY_ID_DEFAULT);
4327 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4328 outsideWindow->setWatchOutsideTouch(true);
4329 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004330 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004331
4332 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4335 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004336 window->consumeMotionDown();
4337 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4338 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4339 outsideWindow->consumeMotionEvent(
4340 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4341}
4342
4343/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004344 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4345 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4346 * ACTION_OUTSIDE event is sent per gesture.
4347 */
4348TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4349 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004351 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4352 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004353 window->setWatchOutsideTouch(true);
4354 window->setFrame(Rect{0, 0, 100, 100});
4355 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004356 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4357 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004358 secondWindow->setFrame(Rect{100, 100, 200, 200});
4359 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004360 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4361 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004362 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004363 mDispatcher->onWindowInfosChanged(
4364 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004365
4366 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4368 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4369 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004370 window->assertNoEvents();
4371 secondWindow->assertNoEvents();
4372
4373 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4374 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004375 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4376 ADISPLAY_ID_DEFAULT,
4377 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004378 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4379 window->consumeMotionEvent(
4380 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004381 secondWindow->consumeMotionDown();
4382 thirdWindow->assertNoEvents();
4383
4384 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4385 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004386 mDispatcher->notifyMotion(
4387 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4388 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004389 window->assertNoEvents();
4390 secondWindow->consumeMotionMove();
4391 thirdWindow->consumeMotionDown();
4392}
4393
Prabir Pradhan814fe082022-07-22 20:22:18 +00004394TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4395 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004396 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4397 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004398 window->setFocusable(true);
4399
Patrick Williamsd828f302023-04-28 17:52:08 -05004400 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004401 setFocusedWindow(window);
4402
4403 window->consumeFocusEvent(true);
4404
Prabir Pradhan678438e2023-04-13 19:32:51 +00004405 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4406 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4407 mDispatcher->notifyKey(keyDown);
4408 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004409
4410 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4411 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4412
4413 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004414 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004415
4416 window->consumeFocusEvent(false);
4417
Prabir Pradhan678438e2023-04-13 19:32:51 +00004418 mDispatcher->notifyKey(keyDown);
4419 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004420 window->assertNoEvents();
4421}
4422
Arthur Hung96483742022-11-15 03:30:48 +00004423TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4425 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4426 "Fake Window", ADISPLAY_ID_DEFAULT);
4427 // Ensure window is non-split and have some transform.
4428 window->setPreventSplitting(true);
4429 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004431
4432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004434 {50, 50}))
4435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4436 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4437
4438 const MotionEvent secondFingerDownEvent =
4439 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4440 .displayId(ADISPLAY_ID_DEFAULT)
4441 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004442 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4443 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004444 .build();
4445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004446 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004447 InputEventInjectionSync::WAIT_FOR_RESULT))
4448 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4449
4450 const MotionEvent* event = window->consumeMotion();
4451 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4452 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4453 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4454 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4455 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4456}
4457
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004458/**
4459 * Two windows: a splittable and a non-splittable.
4460 * The non-splittable window shouldn't receive any "incomplete" gestures.
4461 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4462 * The second pointer should be dropped because the initial window is splittable, so it won't get
4463 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4464 * "incomplete" gestures.
4465 */
4466TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4468 sp<FakeWindowHandle> leftWindow =
4469 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4470 ADISPLAY_ID_DEFAULT);
4471 leftWindow->setPreventSplitting(false);
4472 leftWindow->setFrame(Rect(0, 0, 100, 100));
4473 sp<FakeWindowHandle> rightWindow =
4474 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4475 ADISPLAY_ID_DEFAULT);
4476 rightWindow->setPreventSplitting(true);
4477 rightWindow->setFrame(Rect(100, 100, 200, 200));
4478 mDispatcher->onWindowInfosChanged(
4479 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4480
4481 // Touch down on left, splittable window
4482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4483 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4484 .build());
4485 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4486
4487 mDispatcher->notifyMotion(
4488 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4489 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4490 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4491 .build());
4492 leftWindow->assertNoEvents();
4493 rightWindow->assertNoEvents();
4494}
4495
Harry Cuttsb166c002023-05-09 13:06:05 +00004496TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4497 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4498 sp<FakeWindowHandle> window =
4499 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4500 window->setFrame(Rect(0, 0, 400, 400));
4501 sp<FakeWindowHandle> trustedOverlay =
4502 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4503 ADISPLAY_ID_DEFAULT);
4504 trustedOverlay->setSpy(true);
4505 trustedOverlay->setTrustedOverlay(true);
4506
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004507 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004508
4509 // Start a three-finger touchpad swipe
4510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4511 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4512 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4513 .build());
4514 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4515 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4516 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4517 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4518 .build());
4519 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4520 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4521 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4522 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4523 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4524 .build());
4525
4526 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4527 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4528 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4529
4530 // Move the swipe a bit
4531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4532 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4533 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4534 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4535 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4536 .build());
4537
4538 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4539
4540 // End the swipe
4541 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4542 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4543 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4544 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4545 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4546 .build());
4547 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4548 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4549 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4550 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4551 .build());
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4553 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4554 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4555 .build());
4556
4557 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4558 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4559 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4560
4561 window->assertNoEvents();
4562}
4563
4564TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4566 sp<FakeWindowHandle> window =
4567 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4568 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004569 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004570
4571 // Start a three-finger touchpad swipe
4572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4573 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4574 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4575 .build());
4576 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4577 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4578 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4579 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4580 .build());
4581 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4582 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4583 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4584 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4585 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4586 .build());
4587
4588 // Move the swipe a bit
4589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4590 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4591 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4592 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4593 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4594 .build());
4595
4596 // End the swipe
4597 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4598 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4599 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4600 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4601 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4602 .build());
4603 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4604 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4605 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4606 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4607 .build());
4608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4609 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4610 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4611 .build());
4612
4613 window->assertNoEvents();
4614}
4615
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004616/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004617 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4618 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004619 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004620 */
4621TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4623 sp<FakeWindowHandle> window =
4624 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4625 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004626 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004627
4628 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4630 .downTime(baseTime + 10)
4631 .eventTime(baseTime + 10)
4632 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4633 .build());
4634
4635 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4636
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004637 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004638 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004639
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004640 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004641
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004642 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4643 .downTime(baseTime + 10)
4644 .eventTime(baseTime + 30)
4645 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4646 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4647 .build());
4648
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004649 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4650
4651 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004652 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4653 .downTime(baseTime + 10)
4654 .eventTime(baseTime + 40)
4655 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4656 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4657 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004658
4659 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4660
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4662 .downTime(baseTime + 10)
4663 .eventTime(baseTime + 50)
4664 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4665 .build());
4666
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004667 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4668
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4670 .downTime(baseTime + 60)
4671 .eventTime(baseTime + 60)
4672 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4673 .build());
4674
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004675 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004676}
4677
4678/**
Hu Guo771a7692023-09-17 20:51:08 +08004679 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4680 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4681 * its coordinates should be converted by the transform of the windows of target screen.
4682 */
4683TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4684 // This case will create a window and a spy window on the default display and mirror
4685 // window on the second display. cancel event is sent through spy window pilferPointers
4686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4687
4688 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4689 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4690 spyWindowDefaultDisplay->setTrustedOverlay(true);
4691 spyWindowDefaultDisplay->setSpy(true);
4692
4693 sp<FakeWindowHandle> windowDefaultDisplay =
4694 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4695 ADISPLAY_ID_DEFAULT);
4696 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4697
4698 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4699 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4700
4701 // Add the windows to the dispatcher
4702 mDispatcher->onWindowInfosChanged(
4703 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4704 *windowSecondDisplay->getInfo()},
4705 {},
4706 0,
4707 0});
4708
4709 // Send down to ADISPLAY_ID_DEFAULT
4710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4712 {100, 100}))
4713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4714
4715 spyWindowDefaultDisplay->consumeMotionDown();
4716 windowDefaultDisplay->consumeMotionDown();
4717
4718 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4719
4720 // windowDefaultDisplay gets cancel
4721 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4722 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4723
4724 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4725 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4726 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4727 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4728 EXPECT_EQ(100, event->getX(0));
4729 EXPECT_EQ(100, event->getY(0));
4730}
4731
4732/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004733 * Ensure the correct coordinate spaces are used by InputDispatcher.
4734 *
4735 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4736 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4737 * space.
4738 */
4739class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4740public:
4741 void SetUp() override {
4742 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004743 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004744 }
4745
4746 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4747 gui::DisplayInfo info;
4748 info.displayId = displayId;
4749 info.transform = transform;
4750 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004751 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004752 }
4753
4754 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4755 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004756 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004757 }
4758
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004759 void removeAllWindowsAndDisplays() {
4760 mDisplayInfos.clear();
4761 mWindowInfos.clear();
4762 }
4763
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004764 // Set up a test scenario where the display has a scaled projection and there are two windows
4765 // on the display.
4766 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4767 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4768 // respectively.
4769 ui::Transform displayTransform;
4770 displayTransform.set(2, 0, 0, 4);
4771 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4772
4773 std::shared_ptr<FakeApplicationHandle> application =
4774 std::make_shared<FakeApplicationHandle>();
4775
4776 // Add two windows to the display. Their frames are represented in the display space.
4777 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004778 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4779 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004780 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4781 addWindow(firstWindow);
4782
4783 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004784 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4785 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004786 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4787 addWindow(secondWindow);
4788 return {std::move(firstWindow), std::move(secondWindow)};
4789 }
4790
4791private:
4792 std::vector<gui::DisplayInfo> mDisplayInfos;
4793 std::vector<gui::WindowInfo> mWindowInfos;
4794};
4795
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004796TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004797 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4798 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004799 // selected so that if the hit test was performed with the point and the bounds being in
4800 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004801 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4802 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4803 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004804
4805 firstWindow->consumeMotionDown();
4806 secondWindow->assertNoEvents();
4807}
4808
4809// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4810// the event should be treated as being in the logical display space.
4811TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4812 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4813 // Send down to the first window. The point is represented in the logical display space. The
4814 // point is selected so that if the hit test was done in logical display space, then it would
4815 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004816 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004817 PointF{75 * 2, 55 * 4});
4818
4819 firstWindow->consumeMotionDown();
4820 secondWindow->assertNoEvents();
4821}
4822
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004823// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4824// event should be treated as being in the logical display space.
4825TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4826 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4827
4828 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4829 ui::Transform injectedEventTransform;
4830 injectedEventTransform.set(matrix);
4831 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4832 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4833
4834 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4835 .displayId(ADISPLAY_ID_DEFAULT)
4836 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004837 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004838 .x(untransformedPoint.x)
4839 .y(untransformedPoint.y))
4840 .build();
4841 event.transform(matrix);
4842
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004843 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004844 InputEventInjectionSync::WAIT_FOR_RESULT);
4845
4846 firstWindow->consumeMotionDown();
4847 secondWindow->assertNoEvents();
4848}
4849
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004850TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4851 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4852
4853 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004854 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4855 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4856 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004857
4858 firstWindow->assertNoEvents();
4859 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004860 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004861 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4862
4863 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4864 EXPECT_EQ(300, event->getRawX(0));
4865 EXPECT_EQ(880, event->getRawY(0));
4866
4867 // Ensure that the x and y values are in the window's coordinate space.
4868 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4869 // the logical display space. This will be the origin of the window space.
4870 EXPECT_EQ(100, event->getX(0));
4871 EXPECT_EQ(80, event->getY(0));
4872}
4873
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004874TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4875 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4876 // The monitor will always receive events in the logical display's coordinate space, because
4877 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004878 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004879
4880 // Send down to the first window.
4881 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4882 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4883 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4884 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4885
4886 // Second pointer goes down on second window.
4887 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4888 ADISPLAY_ID_DEFAULT,
4889 {PointF{50, 100}, PointF{150, 220}}));
4890 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4891 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4892 {1, PointF{300, 880}}};
4893 monitor.consumeMotionEvent(
4894 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4895
4896 mDispatcher->cancelCurrentTouch();
4897
4898 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4899 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4900 monitor.consumeMotionEvent(
4901 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4902}
4903
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004904TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4905 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4906
4907 // Send down to the first window.
4908 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4909 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4910 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4911
4912 // The pointer is transferred to the second window, and the second window receives it in the
4913 // correct coordinate space.
4914 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4915 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4916 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4917}
4918
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004919TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4920 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4921
4922 // Send hover move to the second window, and ensure it shows up as hover enter.
4923 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4924 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4925 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4926 WithCoords(100, 80), WithRawCoords(300, 880)));
4927
4928 // Touch down at the same location and ensure a hover exit is synthesized.
4929 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4930 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4931 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4932 WithRawCoords(300, 880)));
4933 secondWindow->consumeMotionEvent(
4934 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4935 secondWindow->assertNoEvents();
4936 firstWindow->assertNoEvents();
4937}
4938
Prabir Pradhan453ae732023-10-13 14:30:14 +00004939// Same as above, but while the window is being mirrored.
4940TEST_F(InputDispatcherDisplayProjectionTest,
4941 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4942 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4943
4944 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4945 ui::Transform secondDisplayTransform;
4946 secondDisplayTransform.set(matrix);
4947 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4948
4949 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4950 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4951 addWindow(secondWindowClone);
4952
4953 // Send hover move to the second window, and ensure it shows up as hover enter.
4954 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4955 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4956 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4957 WithCoords(100, 80), WithRawCoords(300, 880)));
4958
4959 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4960 // display.
4961 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4962 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4963 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4964 WithRawCoords(300, 880)));
4965 secondWindow->consumeMotionEvent(
4966 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4967 secondWindow->assertNoEvents();
4968 firstWindow->assertNoEvents();
4969}
4970
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004971TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4972 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4973
4974 // Send hover enter to second window
4975 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4976 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4977 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4978 WithCoords(100, 80), WithRawCoords(300, 880)));
4979
4980 mDispatcher->cancelCurrentTouch();
4981
4982 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4983 WithRawCoords(300, 880)));
4984 secondWindow->assertNoEvents();
4985 firstWindow->assertNoEvents();
4986}
4987
Prabir Pradhan453ae732023-10-13 14:30:14 +00004988// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004989TEST_F(InputDispatcherDisplayProjectionTest,
4990 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4991 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4992
4993 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4994 ui::Transform secondDisplayTransform;
4995 secondDisplayTransform.set(matrix);
4996 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4997
4998 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4999 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5000 addWindow(secondWindowClone);
5001
5002 // Send hover enter to second window
5003 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5004 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5005 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5006 WithCoords(100, 80), WithRawCoords(300, 880),
5007 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5008
5009 mDispatcher->cancelCurrentTouch();
5010
5011 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5012 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5013 WithRawCoords(300, 880),
5014 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5015 secondWindow->assertNoEvents();
5016 firstWindow->assertNoEvents();
5017}
5018
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005019/** Ensure consistent behavior of InputDispatcher in all orientations. */
5020class InputDispatcherDisplayOrientationFixture
5021 : public InputDispatcherDisplayProjectionTest,
5022 public ::testing::WithParamInterface<ui::Rotation> {};
5023
5024// This test verifies the touchable region of a window for all rotations of the display by tapping
5025// in different locations on the display, specifically points close to the four corners of a
5026// window.
5027TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5028 constexpr static int32_t displayWidth = 400;
5029 constexpr static int32_t displayHeight = 800;
5030
5031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5032
5033 const auto rotation = GetParam();
5034
5035 // Set up the display with the specified rotation.
5036 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5037 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5038 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5039 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5040 logicalDisplayWidth, logicalDisplayHeight);
5041 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5042
5043 // Create a window with its bounds determined in the logical display.
5044 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5045 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5046 sp<FakeWindowHandle> window =
5047 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5048 window->setFrame(frameInDisplay, displayTransform);
5049 addWindow(window);
5050
5051 // The following points in logical display space should be inside the window.
5052 static const std::array<vec2, 4> insidePoints{
5053 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5054 for (const auto pointInsideWindow : insidePoints) {
5055 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5056 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005057 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5058 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5059 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005060 window->consumeMotionDown();
5061
Prabir Pradhan678438e2023-04-13 19:32:51 +00005062 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5063 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5064 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005065 window->consumeMotionUp();
5066 }
5067
5068 // The following points in logical display space should be outside the window.
5069 static const std::array<vec2, 5> outsidePoints{
5070 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5071 for (const auto pointOutsideWindow : outsidePoints) {
5072 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5073 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005074 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5075 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5076 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005077
Prabir Pradhan678438e2023-04-13 19:32:51 +00005078 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5079 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5080 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005081 }
5082 window->assertNoEvents();
5083}
5084
5085// Run the precision tests for all rotations.
5086INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5087 InputDispatcherDisplayOrientationFixture,
5088 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5089 ui::ROTATION_270),
5090 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5091 return ftl::enum_string(testParamInfo.param);
5092 });
5093
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005094using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5095 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005096
5097class TransferTouchFixture : public InputDispatcherTest,
5098 public ::testing::WithParamInterface<TransferFunction> {};
5099
5100TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005102
5103 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005104 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005105 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5106 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005107 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005108 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005109 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5110 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005111 sp<FakeWindowHandle> wallpaper =
5112 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5113 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005114 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005115 mDispatcher->onWindowInfosChanged(
5116 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005117
5118 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005119 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5120 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005121
Svet Ganov5d3bc372020-01-26 23:11:07 -08005122 // Only the first window should get the down event
5123 firstWindow->consumeMotionDown();
5124 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005125 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005126
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005127 // Transfer touch to the second window
5128 TransferFunction f = GetParam();
5129 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5130 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005131 // The first window gets cancel and the second gets down
5132 firstWindow->consumeMotionCancel();
5133 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005134 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005135
5136 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005137 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5138 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005139 // The first window gets no events and the second gets up
5140 firstWindow->assertNoEvents();
5141 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005142 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005143}
5144
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005145/**
5146 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5147 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5148 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5149 * natural to the user.
5150 * In this test, we are sending a pointer to both spy window and first window. We then try to
5151 * transfer touch to the second window. The dispatcher should identify the first window as the
5152 * one that should lose the gesture, and therefore the action should be to move the gesture from
5153 * the first window to the second.
5154 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5155 * the other API, as well.
5156 */
5157TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5159
5160 // Create a couple of windows + a spy window
5161 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005162 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005163 spyWindow->setTrustedOverlay(true);
5164 spyWindow->setSpy(true);
5165 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005166 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005167 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005168 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005169
5170 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005171 mDispatcher->onWindowInfosChanged(
5172 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005173
5174 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005175 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5176 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005177 // Only the first window and spy should get the down event
5178 spyWindow->consumeMotionDown();
5179 firstWindow->consumeMotionDown();
5180
5181 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5182 // if f === 'transferTouch'.
5183 TransferFunction f = GetParam();
5184 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5185 ASSERT_TRUE(success);
5186 // The first window gets cancel and the second gets down
5187 firstWindow->consumeMotionCancel();
5188 secondWindow->consumeMotionDown();
5189
5190 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005191 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5192 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005193 // The first window gets no events and the second+spy get up
5194 firstWindow->assertNoEvents();
5195 spyWindow->consumeMotionUp();
5196 secondWindow->consumeMotionUp();
5197}
5198
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005199TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005200 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005201
5202 PointF touchPoint = {10, 10};
5203
5204 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005205 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005206 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5207 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005208 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005209 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5211 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005212 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005213
5214 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005215 mDispatcher->onWindowInfosChanged(
5216 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005217
5218 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005219 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5220 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5221 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005222 // Only the first window should get the down event
5223 firstWindow->consumeMotionDown();
5224 secondWindow->assertNoEvents();
5225
5226 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005227 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5228 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005229 // Only the first window should get the pointer down event
5230 firstWindow->consumeMotionPointerDown(1);
5231 secondWindow->assertNoEvents();
5232
5233 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005234 TransferFunction f = GetParam();
5235 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5236 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005237 // The first window gets cancel and the second gets down and pointer down
5238 firstWindow->consumeMotionCancel();
5239 secondWindow->consumeMotionDown();
5240 secondWindow->consumeMotionPointerDown(1);
5241
5242 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005243 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5244 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005245 // The first window gets nothing and the second gets pointer up
5246 firstWindow->assertNoEvents();
5247 secondWindow->consumeMotionPointerUp(1);
5248
5249 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005250 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5251 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005252 // The first window gets nothing and the second gets up
5253 firstWindow->assertNoEvents();
5254 secondWindow->consumeMotionUp();
5255}
5256
Arthur Hungc539dbb2022-12-08 07:45:36 +00005257TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5259
5260 // Create a couple of windows
5261 sp<FakeWindowHandle> firstWindow =
5262 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5263 ADISPLAY_ID_DEFAULT);
5264 firstWindow->setDupTouchToWallpaper(true);
5265 sp<FakeWindowHandle> secondWindow =
5266 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5267 ADISPLAY_ID_DEFAULT);
5268 secondWindow->setDupTouchToWallpaper(true);
5269
5270 sp<FakeWindowHandle> wallpaper1 =
5271 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5272 wallpaper1->setIsWallpaper(true);
5273
5274 sp<FakeWindowHandle> wallpaper2 =
5275 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5276 wallpaper2->setIsWallpaper(true);
5277 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005278 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5279 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5280 {},
5281 0,
5282 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283
5284 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005285 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5286 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005287
5288 // Only the first window should get the down event
5289 firstWindow->consumeMotionDown();
5290 secondWindow->assertNoEvents();
5291 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5292 wallpaper2->assertNoEvents();
5293
5294 // Transfer touch focus to the second window
5295 TransferFunction f = GetParam();
5296 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5297 ASSERT_TRUE(success);
5298
5299 // The first window gets cancel and the second gets down
5300 firstWindow->consumeMotionCancel();
5301 secondWindow->consumeMotionDown();
5302 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5303 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5304
5305 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005306 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5307 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005308 // The first window gets no events and the second gets up
5309 firstWindow->assertNoEvents();
5310 secondWindow->consumeMotionUp();
5311 wallpaper1->assertNoEvents();
5312 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5313}
5314
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005315// For the cases of single pointer touch and two pointers non-split touch, the api's
5316// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5317// for the case where there are multiple pointers split across several windows.
5318INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5319 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005320 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5321 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005322 return dispatcher->transferTouch(destChannelToken,
5323 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005324 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005325 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5326 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005327 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005328 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005329 }));
5330
Svet Ganov5d3bc372020-01-26 23:11:07 -08005331TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005333
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005334 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005335 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5336 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005337 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005338
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005339 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005340 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5341 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005342 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005343
5344 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005345 mDispatcher->onWindowInfosChanged(
5346 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005347
5348 PointF pointInFirst = {300, 200};
5349 PointF pointInSecond = {300, 600};
5350
5351 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005352 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5353 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5354 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005355 // Only the first window should get the down event
5356 firstWindow->consumeMotionDown();
5357 secondWindow->assertNoEvents();
5358
5359 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005360 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5361 ADISPLAY_ID_DEFAULT,
5362 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005363 // The first window gets a move and the second a down
5364 firstWindow->consumeMotionMove();
5365 secondWindow->consumeMotionDown();
5366
5367 // Transfer touch focus to the second window
5368 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5369 // The first window gets cancel and the new gets pointer down (it already saw down)
5370 firstWindow->consumeMotionCancel();
5371 secondWindow->consumeMotionPointerDown(1);
5372
5373 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005374 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5375 ADISPLAY_ID_DEFAULT,
5376 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005377 // The first window gets nothing and the second gets pointer up
5378 firstWindow->assertNoEvents();
5379 secondWindow->consumeMotionPointerUp(1);
5380
5381 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5383 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005384 // The first window gets nothing and the second gets up
5385 firstWindow->assertNoEvents();
5386 secondWindow->consumeMotionUp();
5387}
5388
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005389// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5390// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5391// touch is not supported, so the touch should continue on those windows and the transferred-to
5392// window should get nothing.
5393TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5395
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005396 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005397 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5398 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005399 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005400
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005401 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005402 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5403 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005404 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005405
5406 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005407 mDispatcher->onWindowInfosChanged(
5408 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005409
5410 PointF pointInFirst = {300, 200};
5411 PointF pointInSecond = {300, 600};
5412
5413 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005414 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5415 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5416 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005417 // Only the first window should get the down event
5418 firstWindow->consumeMotionDown();
5419 secondWindow->assertNoEvents();
5420
5421 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5423 ADISPLAY_ID_DEFAULT,
5424 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005425 // The first window gets a move and the second a down
5426 firstWindow->consumeMotionMove();
5427 secondWindow->consumeMotionDown();
5428
5429 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005430 const bool transferred =
5431 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005432 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5433 ASSERT_FALSE(transferred);
5434 firstWindow->assertNoEvents();
5435 secondWindow->assertNoEvents();
5436
5437 // The rest of the dispatch should proceed as normal
5438 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005439 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5440 ADISPLAY_ID_DEFAULT,
5441 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005442 // The first window gets MOVE and the second gets pointer up
5443 firstWindow->consumeMotionMove();
5444 secondWindow->consumeMotionUp();
5445
5446 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005447 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5448 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005449 // The first window gets nothing and the second gets up
5450 firstWindow->consumeMotionUp();
5451 secondWindow->assertNoEvents();
5452}
5453
Arthur Hungabbb9d82021-09-01 14:52:30 +00005454// This case will create two windows and one mirrored window on the default display and mirror
5455// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5456// the windows info of second display before default display.
5457TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5458 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5459 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005460 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005461 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005462 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005463 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005464 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005465
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005466 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005467 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005468
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005469 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005470 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005471
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005472 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005473 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005474
5475 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005476 mDispatcher->onWindowInfosChanged(
5477 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5478 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5479 *secondWindowInPrimary->getInfo()},
5480 {},
5481 0,
5482 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005483
5484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005485 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005486 {50, 50}))
5487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5488
5489 // Window should receive motion event.
5490 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5491
5492 // Transfer touch focus
5493 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5494 secondWindowInPrimary->getToken()));
5495 // The first window gets cancel.
5496 firstWindowInPrimary->consumeMotionCancel();
5497 secondWindowInPrimary->consumeMotionDown();
5498
5499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005500 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005501 ADISPLAY_ID_DEFAULT, {150, 50}))
5502 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5503 firstWindowInPrimary->assertNoEvents();
5504 secondWindowInPrimary->consumeMotionMove();
5505
5506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005507 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005508 {150, 50}))
5509 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5510 firstWindowInPrimary->assertNoEvents();
5511 secondWindowInPrimary->consumeMotionUp();
5512}
5513
5514// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5515// 'transferTouch' api.
5516TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5518 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005519 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005520 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005521 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005522 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005523 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005524
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005525 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005526 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005527
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005528 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005529 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005530
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005531 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005532 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005533
5534 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005535 mDispatcher->onWindowInfosChanged(
5536 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5537 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5538 *secondWindowInPrimary->getInfo()},
5539 {},
5540 0,
5541 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005542
5543 // Touch on second display.
5544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005545 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5546 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005547 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5548
5549 // Window should receive motion event.
5550 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5551
5552 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005553 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005554
5555 // The first window gets cancel.
5556 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5557 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5558
5559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005560 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005561 SECOND_DISPLAY_ID, {150, 50}))
5562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5563 firstWindowInPrimary->assertNoEvents();
5564 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5565
5566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005567 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5569 firstWindowInPrimary->assertNoEvents();
5570 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5571}
5572
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005573TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005575 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5576 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005577
Vishnu Nair47074b82020-08-14 11:54:47 -07005578 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005579 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005580 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005581
5582 window->consumeFocusEvent(true);
5583
Prabir Pradhan678438e2023-04-13 19:32:51 +00005584 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005585
5586 // Window should receive key down event.
5587 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005588
5589 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005590 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005591 mFakePolicy->assertUserActivityPoked();
5592}
5593
5594TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5596 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5597 "Fake Window", ADISPLAY_ID_DEFAULT);
5598
5599 window->setDisableUserActivity(true);
5600 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005601 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005602 setFocusedWindow(window);
5603
5604 window->consumeFocusEvent(true);
5605
5606 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5607
5608 // Window should receive key down event.
5609 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5610
5611 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005612 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005613 mFakePolicy->assertUserActivityNotPoked();
5614}
5615
5616TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5617 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5618 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5619 "Fake Window", ADISPLAY_ID_DEFAULT);
5620
5621 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005622 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005623 setFocusedWindow(window);
5624
5625 window->consumeFocusEvent(true);
5626
5627 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5628 mDispatcher->waitForIdle();
5629
5630 // System key is not passed down
5631 window->assertNoEvents();
5632
5633 // Should have poked user activity
5634 mFakePolicy->assertUserActivityPoked();
5635}
5636
5637TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5639 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5640 "Fake Window", ADISPLAY_ID_DEFAULT);
5641
5642 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005643 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005644 setFocusedWindow(window);
5645
5646 window->consumeFocusEvent(true);
5647
5648 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5649 mDispatcher->waitForIdle();
5650
5651 // System key is not passed down
5652 window->assertNoEvents();
5653
5654 // Should have poked user activity
5655 mFakePolicy->assertUserActivityPoked();
5656}
5657
5658TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5661 "Fake Window", ADISPLAY_ID_DEFAULT);
5662
5663 window->setDisableUserActivity(true);
5664 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005665 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005666 setFocusedWindow(window);
5667
5668 window->consumeFocusEvent(true);
5669
5670 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5671 mDispatcher->waitForIdle();
5672
5673 // System key is not passed down
5674 window->assertNoEvents();
5675
5676 // Should have poked user activity
5677 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005678}
5679
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005680TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5682 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5683 "Fake Window", ADISPLAY_ID_DEFAULT);
5684
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005686
5687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005688 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005689 ADISPLAY_ID_DEFAULT, {100, 100}))
5690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5691
5692 window->consumeMotionEvent(
5693 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5694
5695 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005696 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005697 mFakePolicy->assertUserActivityPoked();
5698}
5699
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005700TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005702 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5703 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005706
Prabir Pradhan678438e2023-04-13 19:32:51 +00005707 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005708 mDispatcher->waitForIdle();
5709
5710 window->assertNoEvents();
5711}
5712
5713// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5714TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005716 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5717 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005718
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005719 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005720
5721 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005722 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005723 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005724 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5725 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005726
5727 // Window should receive only the motion event
5728 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5729 window->assertNoEvents(); // Key event or focus event will not be received
5730}
5731
arthurhungea3f4fc2020-12-21 23:18:53 +08005732TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5734
arthurhungea3f4fc2020-12-21 23:18:53 +08005735 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005736 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5737 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005738 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005739
arthurhungea3f4fc2020-12-21 23:18:53 +08005740 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005741 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5742 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005743 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005744
5745 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005746 mDispatcher->onWindowInfosChanged(
5747 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005748
5749 PointF pointInFirst = {300, 200};
5750 PointF pointInSecond = {300, 600};
5751
5752 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005753 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5754 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5755 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005756 // Only the first window should get the down event
5757 firstWindow->consumeMotionDown();
5758 secondWindow->assertNoEvents();
5759
5760 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005761 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5762 ADISPLAY_ID_DEFAULT,
5763 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005764 // The first window gets a move and the second a down
5765 firstWindow->consumeMotionMove();
5766 secondWindow->consumeMotionDown();
5767
5768 // Send pointer cancel to the second window
5769 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005770 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005771 {pointInFirst, pointInSecond});
5772 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005773 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005774 // The first window gets move and the second gets cancel.
5775 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5776 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5777
5778 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005779 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5780 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005781 // The first window gets up and the second gets nothing.
5782 firstWindow->consumeMotionUp();
5783 secondWindow->assertNoEvents();
5784}
5785
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005786TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5788
5789 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005790 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005792 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5793 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5794 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5795
Harry Cutts33476232023-01-30 19:57:29 +00005796 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005797 window->assertNoEvents();
5798 mDispatcher->waitForIdle();
5799}
5800
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005801using InputDispatcherMonitorTest = InputDispatcherTest;
5802
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005803/**
5804 * Two entities that receive touch: A window, and a global monitor.
5805 * The touch goes to the window, and then the window disappears.
5806 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5807 * for the monitor, as well.
5808 * 1. foregroundWindow
5809 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5810 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005811TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5813 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005814 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005815
Prabir Pradhanfb549072023-10-05 19:17:36 +00005816 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005818 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005820 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005821 {100, 200}))
5822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5823
5824 // Both the foreground window and the global monitor should receive the touch down
5825 window->consumeMotionDown();
5826 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5827
5828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005829 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005830 ADISPLAY_ID_DEFAULT, {110, 200}))
5831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5832
5833 window->consumeMotionMove();
5834 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5835
5836 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005837 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005838 window->consumeMotionCancel();
5839 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5840
5841 // If more events come in, there will be no more foreground window to send them to. This will
5842 // cause a cancel for the monitor, as well.
5843 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005844 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005845 ADISPLAY_ID_DEFAULT, {120, 200}))
5846 << "Injection should fail because the window was removed";
5847 window->assertNoEvents();
5848 // Global monitor now gets the cancel
5849 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5850}
5851
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005852TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005854 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5855 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005856 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005857
Prabir Pradhanfb549072023-10-05 19:17:36 +00005858 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005859
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005861 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005864 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005865}
5866
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005867TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005868 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005869
Chris Yea209fde2020-07-22 13:54:51 -07005870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005871 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5872 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005874
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005878 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005879 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005880
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005881 // Pilfer pointers from the monitor.
5882 // This should not do anything and the window should continue to receive events.
5883 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005884
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005886 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005887 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005889
5890 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5891 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005892}
5893
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005894TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005895 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005896 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5897 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005899 window->setWindowOffset(20, 40);
5900 window->setWindowTransform(0, 1, -1, 0);
5901
Prabir Pradhanfb549072023-10-05 19:17:36 +00005902 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005903
5904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005905 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5907 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5908 MotionEvent* event = monitor.consumeMotion();
5909 // Even though window has transform, gesture monitor must not.
5910 ASSERT_EQ(ui::Transform(), event->getTransform());
5911}
5912
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005913TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005915 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005916
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005917 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005919 << "Injection should fail if there is a monitor, but no touchable window";
5920 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005921}
5922
chaviw81e2bb92019-12-18 15:03:51 -08005923TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005925 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5926 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005927
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005928 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005929
5930 NotifyMotionArgs motionArgs =
5931 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5932 ADISPLAY_ID_DEFAULT);
5933
Prabir Pradhan678438e2023-04-13 19:32:51 +00005934 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005935 // Window should receive motion down event.
5936 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5937
5938 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005939 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005940 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5941 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5942 motionArgs.pointerCoords[0].getX() - 10);
5943
Prabir Pradhan678438e2023-04-13 19:32:51 +00005944 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005945 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005946 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005947}
5948
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005949/**
5950 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5951 * the device default right away. In the test scenario, we check both the default value,
5952 * and the action of enabling / disabling.
5953 */
5954TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005956 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5957 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005958 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005959
5960 // Set focused application.
5961 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005962 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005963
5964 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005965 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005966 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005967 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005968
5969 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005970 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005971 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005972 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005973
5974 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005975 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005976 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005977 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005978 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005979 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005980 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005981 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005982
5983 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005984 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005985 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005986 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005987
5988 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005989 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005990 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005991 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005992 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005993 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005994 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005995 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005996
5997 window->assertNoEvents();
5998}
5999
Gang Wange9087892020-01-07 12:17:14 -05006000TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006002 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6003 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006004
6005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006006 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006007
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006008 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006009 setFocusedWindow(window);
6010
Harry Cutts33476232023-01-30 19:57:29 +00006011 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006012
Prabir Pradhan678438e2023-04-13 19:32:51 +00006013 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6014 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006015
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006016 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006017 ASSERT_NE(event, nullptr);
6018
6019 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6020 ASSERT_NE(verified, nullptr);
6021 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6022
6023 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6024 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6025 ASSERT_EQ(keyArgs.source, verified->source);
6026 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6027
6028 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6029
6030 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006031 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006032 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006033 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6034 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6035 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6036 ASSERT_EQ(0, verifiedKey.repeatCount);
6037}
6038
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006039TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6042 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006043
6044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6045
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006046 ui::Transform transform;
6047 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6048
6049 gui::DisplayInfo displayInfo;
6050 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6051 displayInfo.transform = transform;
6052
Patrick Williamsd828f302023-04-28 17:52:08 -05006053 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006054
Prabir Pradhan678438e2023-04-13 19:32:51 +00006055 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006056 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6057 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006058 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006059
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006060 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006061 ASSERT_NE(event, nullptr);
6062
6063 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6064 ASSERT_NE(verified, nullptr);
6065 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6066
6067 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6068 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6069 EXPECT_EQ(motionArgs.source, verified->source);
6070 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6071
6072 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6073
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006074 const vec2 rawXY =
6075 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6076 motionArgs.pointerCoords[0].getXYValue());
6077 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6078 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006079 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006080 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006081 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006082 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6083 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6084}
6085
chaviw09c8d2d2020-08-24 15:48:26 -07006086/**
6087 * Ensure that separate calls to sign the same data are generating the same key.
6088 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6089 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6090 * tests.
6091 */
6092TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6093 KeyEvent event = getTestKeyEvent();
6094 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6095
6096 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6097 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6098 ASSERT_EQ(hmac1, hmac2);
6099}
6100
6101/**
6102 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6103 */
6104TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6105 KeyEvent event = getTestKeyEvent();
6106 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6107 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6108
6109 verifiedEvent.deviceId += 1;
6110 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6111
6112 verifiedEvent.source += 1;
6113 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6114
6115 verifiedEvent.eventTimeNanos += 1;
6116 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6117
6118 verifiedEvent.displayId += 1;
6119 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6120
6121 verifiedEvent.action += 1;
6122 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6123
6124 verifiedEvent.downTimeNanos += 1;
6125 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6126
6127 verifiedEvent.flags += 1;
6128 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6129
6130 verifiedEvent.keyCode += 1;
6131 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6132
6133 verifiedEvent.scanCode += 1;
6134 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6135
6136 verifiedEvent.metaState += 1;
6137 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6138
6139 verifiedEvent.repeatCount += 1;
6140 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6141}
6142
Vishnu Nair958da932020-08-21 17:12:37 -07006143TEST_F(InputDispatcherTest, SetFocusedWindow) {
6144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6145 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006146 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006147 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006148 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006149 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6150
6151 // Top window is also focusable but is not granted focus.
6152 windowTop->setFocusable(true);
6153 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006154 mDispatcher->onWindowInfosChanged(
6155 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006156 setFocusedWindow(windowSecond);
6157
6158 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006160 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006161
6162 // Focused window should receive event.
6163 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6164 windowTop->assertNoEvents();
6165}
6166
6167TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6169 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006170 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6172
6173 window->setFocusable(true);
6174 // Release channel for window is no longer valid.
6175 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006177 setFocusedWindow(window);
6178
6179 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006180 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006181
6182 // window channel is invalid, so it should not receive any input event.
6183 window->assertNoEvents();
6184}
6185
6186TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6188 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006189 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006190 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006194 setFocusedWindow(window);
6195
6196 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006197 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006198
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006199 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006200 window->assertNoEvents();
6201}
6202
6203TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6204 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6205 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006206 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006207 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006208 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006209 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6210
6211 windowTop->setFocusable(true);
6212 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006213 mDispatcher->onWindowInfosChanged(
6214 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006215 setFocusedWindow(windowTop);
6216 windowTop->consumeFocusEvent(true);
6217
Chavi Weingarten847e8512023-03-29 00:26:09 +00006218 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006219 mDispatcher->onWindowInfosChanged(
6220 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006221 windowSecond->consumeFocusEvent(true);
6222 windowTop->consumeFocusEvent(false);
6223
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006225 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006226
6227 // Focused window should receive event.
6228 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6229}
6230
Chavi Weingarten847e8512023-03-29 00:26:09 +00006231TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6233 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006234 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006235 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006236 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6238
6239 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006240 windowSecond->setFocusable(false);
6241 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006242 mDispatcher->onWindowInfosChanged(
6243 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006244 setFocusedWindow(windowTop);
6245 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006246
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006248 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006249
6250 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006251 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006252 windowSecond->assertNoEvents();
6253}
6254
6255TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6257 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006258 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006259 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006260 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6261 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006262 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6263
6264 window->setFocusable(true);
6265 previousFocusedWindow->setFocusable(true);
6266 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006267 mDispatcher->onWindowInfosChanged(
6268 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006269 setFocusedWindow(previousFocusedWindow);
6270 previousFocusedWindow->consumeFocusEvent(true);
6271
6272 // Requesting focus on invisible window takes focus from currently focused window.
6273 setFocusedWindow(window);
6274 previousFocusedWindow->consumeFocusEvent(false);
6275
6276 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006278 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6279 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006280
6281 // Window does not get focus event or key down.
6282 window->assertNoEvents();
6283
6284 // Window becomes visible.
6285 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006286 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006287
6288 // Window receives focus event.
6289 window->consumeFocusEvent(true);
6290 // Focused window receives key down.
6291 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6292}
6293
Vishnu Nair599f1412021-06-21 10:39:58 -07006294TEST_F(InputDispatcherTest, DisplayRemoved) {
6295 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6296 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006297 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006298 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6299
6300 // window is granted focus.
6301 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006302 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006303 setFocusedWindow(window);
6304 window->consumeFocusEvent(true);
6305
6306 // When a display is removed window loses focus.
6307 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6308 window->consumeFocusEvent(false);
6309}
6310
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006311/**
6312 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6313 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6314 * of the 'slipperyEnterWindow'.
6315 *
6316 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6317 * a way so that the touched location is no longer covered by the top window.
6318 *
6319 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6320 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6321 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6322 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6323 * with ACTION_DOWN).
6324 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6325 * window moved itself away from the touched location and had Flag::SLIPPERY.
6326 *
6327 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6328 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6329 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6330 *
6331 * In this test, we ensure that the event received by the bottom window has
6332 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6333 */
6334TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006335 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006336 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006337
6338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6339 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6340
6341 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006342 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006343 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006344 // Make sure this one overlaps the bottom window
6345 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6346 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6347 // one. Windows with the same owner are not considered to be occluding each other.
6348 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6349
6350 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006351 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006352 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6353
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006354 mDispatcher->onWindowInfosChanged(
6355 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006356
6357 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006358 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6359 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6360 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006361 slipperyExitWindow->consumeMotionDown();
6362 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006363 mDispatcher->onWindowInfosChanged(
6364 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006365
Prabir Pradhan678438e2023-04-13 19:32:51 +00006366 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6367 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6368 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006369
6370 slipperyExitWindow->consumeMotionCancel();
6371
6372 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6373 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6374}
6375
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006376/**
6377 * Two windows, one on the left and another on the right. The left window is slippery. The right
6378 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6379 * touch moves from the left window into the right window, the gesture should continue to go to the
6380 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6381 * reproduces a crash.
6382 */
6383TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6385
6386 sp<FakeWindowHandle> leftSlipperyWindow =
6387 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6388 leftSlipperyWindow->setSlippery(true);
6389 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6390
6391 sp<FakeWindowHandle> rightDropTouchesWindow =
6392 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6393 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6394 rightDropTouchesWindow->setDropInput(true);
6395
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006396 mDispatcher->onWindowInfosChanged(
6397 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006398
6399 // Start touch in the left window
6400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6401 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6402 .build());
6403 leftSlipperyWindow->consumeMotionDown();
6404
6405 // And move it into the right window
6406 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6407 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6408 .build());
6409
6410 // Since the right window isn't eligible to receive input, touch does not slip.
6411 // The left window continues to receive the gesture.
6412 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6413 rightDropTouchesWindow->assertNoEvents();
6414}
6415
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006416/**
6417 * A single window is on screen first. Touch is injected into that window. Next, a second window
6418 * appears. Since the first window is slippery, touch will move from the first window to the second.
6419 */
6420TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6422 sp<FakeWindowHandle> originalWindow =
6423 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6424 originalWindow->setFrame(Rect(0, 0, 200, 200));
6425 originalWindow->setSlippery(true);
6426
6427 sp<FakeWindowHandle> appearingWindow =
6428 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6429 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6430
6431 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6432
6433 // Touch down on the original window
6434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6435 injectMotionEvent(*mDispatcher,
6436 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6437 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6438 .build()));
6439 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6440
6441 // Now, a new window appears. This could be, for example, a notification shade that appears
6442 // after user starts to drag down on the launcher window.
6443 mDispatcher->onWindowInfosChanged(
6444 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6446 injectMotionEvent(*mDispatcher,
6447 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6448 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6449 .build()));
6450 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6451 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6453 injectMotionEvent(*mDispatcher,
6454 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6455 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6456 .build()));
6457 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6458
6459 originalWindow->assertNoEvents();
6460 appearingWindow->assertNoEvents();
6461}
6462
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006463TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006464 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6466
6467 sp<FakeWindowHandle> leftWindow =
6468 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6469 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006470 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006471
6472 sp<FakeWindowHandle> rightSpy =
6473 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6474 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006475 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006476 rightSpy->setSpy(true);
6477 rightSpy->setTrustedOverlay(true);
6478
6479 sp<FakeWindowHandle> rightWindow =
6480 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6481 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006482 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006483
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006484 mDispatcher->onWindowInfosChanged(
6485 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006486
6487 // Touch in the left window
6488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6489 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6490 .build());
6491 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6492 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006493 ASSERT_NO_FATAL_FAILURE(
6494 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006495
6496 // Touch another finger over the right windows
6497 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6498 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6499 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6500 .build());
6501 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6502 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6503 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6504 mDispatcher->waitForIdle();
6505 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006506 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6507 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006508
6509 // Release finger over left window. The UP actions are not treated as device interaction.
6510 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6511 // is part of the UP action, we do not treat this as device interaction.
6512 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6513 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6514 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6515 .build());
6516 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6517 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6518 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6519 mDispatcher->waitForIdle();
6520 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6521
6522 // Move remaining finger
6523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6524 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6525 .build());
6526 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6527 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6528 mDispatcher->waitForIdle();
6529 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006530 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006531
6532 // Release all fingers
6533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6534 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6535 .build());
6536 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6537 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6538 mDispatcher->waitForIdle();
6539 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6540}
6541
6542TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6544
6545 sp<FakeWindowHandle> window =
6546 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6547 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006548 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006549
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006550 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006551 setFocusedWindow(window);
6552 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6553
6554 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6555 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6556 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006557 ASSERT_NO_FATAL_FAILURE(
6558 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006559
6560 // The UP actions are not treated as device interaction.
6561 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6562 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6563 mDispatcher->waitForIdle();
6564 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6565}
6566
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006567class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6568protected:
6569 std::shared_ptr<FakeApplicationHandle> mApp;
6570 sp<FakeWindowHandle> mWindow;
6571
6572 virtual void SetUp() override {
6573 InputDispatcherTest::SetUp();
6574
6575 mApp = std::make_shared<FakeApplicationHandle>();
6576
6577 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6578 mWindow->setFrame(Rect(0, 0, 100, 100));
6579
6580 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6581 setFocusedWindow(mWindow);
6582 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6583 }
6584
6585 void setFallback(int32_t keycode) {
6586 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6587 return KeyEventBuilder(event).keyCode(keycode).build();
6588 });
6589 }
6590
6591 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6592 KeyEvent* event = mWindow->consumeKey(handled);
6593 ASSERT_NE(event, nullptr) << "Did not receive key event";
6594 ASSERT_THAT(*event, matcher);
6595 }
6596};
6597
6598TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6599 mDispatcher->notifyKey(
6600 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6601 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6602 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6603}
6604
6605TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6606 mDispatcher->notifyKey(
6607 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6608 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6609 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6610}
6611
6612TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6613 mDispatcher->notifyKey(
6614 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6615
6616 // Do not handle this key event.
6617 consumeKey(/*handled=*/false,
6618 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6619 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6620
6621 // Since the policy did not request any fallback to be generated, ensure there are no events.
6622 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6623}
6624
6625TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6626 setFallback(AKEYCODE_B);
6627 mDispatcher->notifyKey(
6628 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6629
6630 // Do not handle this key event.
6631 consumeKey(/*handled=*/false,
6632 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6633
6634 // Since the key was not handled, ensure the fallback event was dispatched instead.
6635 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6636 consumeKey(/*handled=*/true,
6637 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6638 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6639
6640 // Release the original key, and ensure the fallback key is also released.
6641 mDispatcher->notifyKey(
6642 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6643 consumeKey(/*handled=*/false,
6644 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6645 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6646 consumeKey(/*handled=*/true,
6647 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6648 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6649
6650 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6651 mWindow->assertNoEvents();
6652}
6653
6654TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6655 setFallback(AKEYCODE_B);
6656 mDispatcher->notifyKey(
6657 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6658
6659 // Do not handle this key event, but handle the fallback.
6660 consumeKey(/*handled=*/false,
6661 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6662 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6663 consumeKey(/*handled=*/true,
6664 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6665 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6666
6667 // Release the original key, and ensure the fallback key is also released.
6668 mDispatcher->notifyKey(
6669 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6670 // But this time, the app handles the original key.
6671 consumeKey(/*handled=*/true,
6672 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6673 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6674 // Ensure the fallback key is canceled.
6675 consumeKey(/*handled=*/true,
6676 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6677 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6678
6679 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6680 mWindow->assertNoEvents();
6681}
6682
6683TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6684 setFallback(AKEYCODE_B);
6685 mDispatcher->notifyKey(
6686 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6687
6688 // Do not handle this key event.
6689 consumeKey(/*handled=*/false,
6690 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6691 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6692 // App does not handle the fallback either, so ensure another fallback is not generated.
6693 setFallback(AKEYCODE_C);
6694 consumeKey(/*handled=*/false,
6695 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6696 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6697
6698 // Release the original key, and ensure the fallback key is also released.
6699 setFallback(AKEYCODE_B);
6700 mDispatcher->notifyKey(
6701 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6702 consumeKey(/*handled=*/false,
6703 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6704 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6705 consumeKey(/*handled=*/false,
6706 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6707 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6708
6709 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6710 mWindow->assertNoEvents();
6711}
6712
6713TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6714 setFallback(AKEYCODE_B);
6715 mDispatcher->notifyKey(
6716 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6717
6718 // Do not handle this key event, so fallback is generated.
6719 consumeKey(/*handled=*/false,
6720 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6721 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6722 consumeKey(/*handled=*/true,
6723 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6724 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6725
6726 // Release the original key, but assume the policy is misbehaving and it
6727 // generates an inconsistent fallback to the one from the DOWN event.
6728 setFallback(AKEYCODE_C);
6729 mDispatcher->notifyKey(
6730 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6731 consumeKey(/*handled=*/false,
6732 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6733 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6734 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6735 consumeKey(/*handled=*/true,
6736 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6737 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6738
6739 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6740 mWindow->assertNoEvents();
6741}
6742
6743TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6744 setFallback(AKEYCODE_B);
6745 mDispatcher->notifyKey(
6746 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6747
6748 // Do not handle this key event, so fallback is generated.
6749 consumeKey(/*handled=*/false,
6750 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6751 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6752 consumeKey(/*handled=*/true,
6753 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6754 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6755
6756 // The original key is canceled.
6757 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6758 .keyCode(AKEYCODE_A)
6759 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6760 .build());
6761 consumeKey(/*handled=*/false,
6762 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6763 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6764 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6765 // Ensure the fallback key is also canceled due to the original key being canceled.
6766 consumeKey(/*handled=*/true,
6767 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6768 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6769
6770 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6771 mWindow->assertNoEvents();
6772}
6773
Garfield Tan1c7bc862020-01-28 13:24:04 -08006774class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6775protected:
6776 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6777 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6778
Chris Yea209fde2020-07-22 13:54:51 -07006779 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006780 sp<FakeWindowHandle> mWindow;
6781
6782 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006783 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006784 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006785 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006786 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006787 ASSERT_EQ(OK, mDispatcher->start());
6788
6789 setUpWindow();
6790 }
6791
6792 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006793 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006794 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006795
Vishnu Nair47074b82020-08-14 11:54:47 -07006796 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006797 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006798 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006799 mWindow->consumeFocusEvent(true);
6800 }
6801
Chris Ye2ad95392020-09-01 13:44:44 -07006802 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006803 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006804 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006805 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006806 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006807
6808 // Window should receive key down event.
6809 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6810 }
6811
6812 void expectKeyRepeatOnce(int32_t repeatCount) {
6813 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006814 mWindow->consumeKeyEvent(
6815 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006816 }
6817
Chris Ye2ad95392020-09-01 13:44:44 -07006818 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006819 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006820 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006821 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006822 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006823
6824 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006825 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006826 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006827 }
6828};
6829
6830TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006831 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006832 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6833 expectKeyRepeatOnce(repeatCount);
6834 }
6835}
6836
6837TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006838 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006839 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6840 expectKeyRepeatOnce(repeatCount);
6841 }
Harry Cutts33476232023-01-30 19:57:29 +00006842 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006843 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006844 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6845 expectKeyRepeatOnce(repeatCount);
6846 }
6847}
6848
6849TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006850 sendAndConsumeKeyDown(/*deviceId=*/1);
6851 expectKeyRepeatOnce(/*repeatCount=*/1);
6852 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006853 mWindow->assertNoEvents();
6854}
6855
6856TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006857 sendAndConsumeKeyDown(/*deviceId=*/1);
6858 expectKeyRepeatOnce(/*repeatCount=*/1);
6859 sendAndConsumeKeyDown(/*deviceId=*/2);
6860 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006861 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006862 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006863 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006864 expectKeyRepeatOnce(/*repeatCount=*/2);
6865 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006866 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006867 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006868 mWindow->assertNoEvents();
6869}
6870
6871TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006872 sendAndConsumeKeyDown(/*deviceId=*/1);
6873 expectKeyRepeatOnce(/*repeatCount=*/1);
6874 sendAndConsumeKeyDown(/*deviceId=*/2);
6875 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006876 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006877 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006878 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006879 mWindow->assertNoEvents();
6880}
6881
liushenxiang42232912021-05-21 20:24:09 +08006882TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6883 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006884 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006885 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006886 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6887 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6888 mWindow->assertNoEvents();
6889}
6890
Garfield Tan1c7bc862020-01-28 13:24:04 -08006891TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006892 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006893 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006894 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006895 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006896 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6897 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6898 IdGenerator::getSource(repeatEvent->getId()));
6899 }
6900}
6901
6902TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006903 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006904 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006905
6906 std::unordered_set<int32_t> idSet;
6907 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006908 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006909 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6910 int32_t id = repeatEvent->getId();
6911 EXPECT_EQ(idSet.end(), idSet.find(id));
6912 idSet.insert(id);
6913 }
6914}
6915
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006916/* Test InputDispatcher for MultiDisplay */
6917class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6918public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006919 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006920 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006921
Chris Yea209fde2020-07-22 13:54:51 -07006922 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006923 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006924 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006925
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006926 // Set focus window for primary display, but focused display would be second one.
6927 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006928 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006929 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6930
Vishnu Nair958da932020-08-21 17:12:37 -07006931 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006932 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006933
Chris Yea209fde2020-07-22 13:54:51 -07006934 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006935 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006936 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006937 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006938 // Set focus display to second one.
6939 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6940 // Set focus window for second display.
6941 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006942 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006943 mDispatcher->onWindowInfosChanged(
6944 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006945 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006946 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006947 }
6948
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006949 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006950 InputDispatcherTest::TearDown();
6951
Chris Yea209fde2020-07-22 13:54:51 -07006952 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006953 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006954 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006955 windowInSecondary.clear();
6956 }
6957
6958protected:
Chris Yea209fde2020-07-22 13:54:51 -07006959 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006960 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006961 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006962 sp<FakeWindowHandle> windowInSecondary;
6963};
6964
6965TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6966 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006970 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006971 windowInSecondary->assertNoEvents();
6972
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006973 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006977 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006978 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006979}
6980
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006981TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006982 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006984 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006985 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006986 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006987 windowInSecondary->assertNoEvents();
6988
6989 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006991 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006992 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006993 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006994
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006995 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006996 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006997
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006998 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006999 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007000 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007001
7002 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007003 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007004 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007005 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007006 windowInSecondary->assertNoEvents();
7007}
7008
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007009// Test per-display input monitors for motion event.
7010TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007011 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007012 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007013 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007014 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007015
7016 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007018 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007020 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007021 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007022 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007023 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007024
7025 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007027 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007029 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007030 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007031 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007032 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007033
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007034 // Lift up the touch from the second display
7035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007036 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7038 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7039 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7040
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007041 // Test inject a non-pointer motion event.
7042 // If specific a display, it will dispatch to the focused window of particular display,
7043 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007045 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007047 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007048 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007049 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007050 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007051}
7052
7053// Test per-display input monitors for key event.
7054TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007055 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007056 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007057 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007058 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007059 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007060
7061 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007064 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007065 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007066 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007067 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007068}
7069
Vishnu Nair958da932020-08-21 17:12:37 -07007070TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7071 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007072 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007073 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007074 mDispatcher->onWindowInfosChanged(
7075 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7076 *windowInSecondary->getInfo()},
7077 {},
7078 0,
7079 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007080 setFocusedWindow(secondWindowInPrimary);
7081 windowInPrimary->consumeFocusEvent(false);
7082 secondWindowInPrimary->consumeFocusEvent(true);
7083
7084 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7086 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007087 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007088 windowInPrimary->assertNoEvents();
7089 windowInSecondary->assertNoEvents();
7090 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7091}
7092
Arthur Hungdfd528e2021-12-08 13:23:04 +00007093TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7094 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007095 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007096 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007097 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007098
7099 // Test touch down on primary display.
7100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007101 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7103 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7104 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7105
7106 // Test touch down on second display.
7107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007108 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7110 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7111 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7112
7113 // Trigger cancel touch.
7114 mDispatcher->cancelCurrentTouch();
7115 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7116 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7117 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7118 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7119
7120 // Test inject a move motion event, no window/monitor should receive the event.
7121 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007122 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007123 ADISPLAY_ID_DEFAULT, {110, 200}))
7124 << "Inject motion event should return InputEventInjectionResult::FAILED";
7125 windowInPrimary->assertNoEvents();
7126 monitorInPrimary.assertNoEvents();
7127
7128 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007129 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007130 SECOND_DISPLAY_ID, {110, 200}))
7131 << "Inject motion event should return InputEventInjectionResult::FAILED";
7132 windowInSecondary->assertNoEvents();
7133 monitorInSecondary.assertNoEvents();
7134}
7135
Jackal Guof9696682018-10-05 12:23:23 +08007136class InputFilterTest : public InputDispatcherTest {
7137protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007138 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7139 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007140 NotifyMotionArgs motionArgs;
7141
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007142 motionArgs =
7143 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007144 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007145 motionArgs =
7146 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007147 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007148 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007149 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007150 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007151 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007152 } else {
7153 mFakePolicy->assertFilterInputEventWasNotCalled();
7154 }
7155 }
7156
7157 void testNotifyKey(bool expectToBeFiltered) {
7158 NotifyKeyArgs keyArgs;
7159
7160 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007161 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007162 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007163 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007164 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007165
7166 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007167 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007168 } else {
7169 mFakePolicy->assertFilterInputEventWasNotCalled();
7170 }
7171 }
7172};
7173
7174// Test InputFilter for MotionEvent
7175TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7176 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007177 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7178 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007179
7180 // Enable InputFilter
7181 mDispatcher->setInputFilterEnabled(true);
7182 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007183 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7184 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007185
7186 // Disable InputFilter
7187 mDispatcher->setInputFilterEnabled(false);
7188 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007189 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7190 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007191}
7192
7193// Test InputFilter for KeyEvent
7194TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7195 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007196 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007197
7198 // Enable InputFilter
7199 mDispatcher->setInputFilterEnabled(true);
7200 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007201 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007202
7203 // Disable InputFilter
7204 mDispatcher->setInputFilterEnabled(false);
7205 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007206 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007207}
7208
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007209// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7210// logical display coordinate space.
7211TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7212 ui::Transform firstDisplayTransform;
7213 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7214 ui::Transform secondDisplayTransform;
7215 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7216
7217 std::vector<gui::DisplayInfo> displayInfos(2);
7218 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7219 displayInfos[0].transform = firstDisplayTransform;
7220 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7221 displayInfos[1].transform = secondDisplayTransform;
7222
Patrick Williamsd828f302023-04-28 17:52:08 -05007223 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007224
7225 // Enable InputFilter
7226 mDispatcher->setInputFilterEnabled(true);
7227
7228 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007229 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7230 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007231}
7232
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007233class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7234protected:
7235 virtual void SetUp() override {
7236 InputDispatcherTest::SetUp();
7237
7238 /**
7239 * We don't need to enable input filter to test the injected event policy, but we enabled it
7240 * here to make the tests more realistic, since this policy only matters when inputfilter is
7241 * on.
7242 */
7243 mDispatcher->setInputFilterEnabled(true);
7244
7245 std::shared_ptr<InputApplicationHandle> application =
7246 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007247 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7248 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007249
7250 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7251 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007252 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007253 setFocusedWindow(mWindow);
7254 mWindow->consumeFocusEvent(true);
7255 }
7256
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007257 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7258 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007259 KeyEvent event;
7260
7261 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7262 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7263 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007264 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007265 const int32_t additionalPolicyFlags =
7266 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007268 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007269 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007270 policyFlags | additionalPolicyFlags));
7271
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007272 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007273 }
7274
7275 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7276 int32_t flags) {
7277 MotionEvent event;
7278 PointerProperties pointerProperties[1];
7279 PointerCoords pointerCoords[1];
7280 pointerProperties[0].clear();
7281 pointerProperties[0].id = 0;
7282 pointerCoords[0].clear();
7283 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7284 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7285
7286 ui::Transform identityTransform;
7287 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7288 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7289 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7290 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7291 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007292 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007293 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007294 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007295
7296 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007298 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007299 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007300 policyFlags | additionalPolicyFlags));
7301
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007302 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007303 }
7304
7305private:
7306 sp<FakeWindowHandle> mWindow;
7307};
7308
7309TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007310 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7311 // filter. Without it, the event will no different from a regularly injected event, and the
7312 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007313 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7314 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007315}
7316
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007317TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007318 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007319 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007320 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7321}
7322
7323TEST_F(InputFilterInjectionPolicyTest,
7324 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7325 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007326 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007327 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007328}
7329
7330TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007331 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7332 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007333}
7334
chaviwfd6d3512019-03-25 13:23:49 -07007335class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007336 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007337 InputDispatcherTest::SetUp();
7338
Chris Yea209fde2020-07-22 13:54:51 -07007339 std::shared_ptr<FakeApplicationHandle> application =
7340 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007341 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007342 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007343 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007344
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007345 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007346 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007347 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007348
7349 // Set focused application.
7350 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007351 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007352
7353 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007354 mDispatcher->onWindowInfosChanged(
7355 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007356 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007357 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007358 }
7359
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007360 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007361 InputDispatcherTest::TearDown();
7362
7363 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007364 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007365 }
7366
7367protected:
7368 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007369 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007370 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007371};
7372
7373// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7374// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7375// the onPointerDownOutsideFocus callback.
7376TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007378 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007379 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007381 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007382
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007383 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007384 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7385}
7386
7387// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7388// DOWN on the window that doesn't have focus. Ensure no window received the
7389// onPointerDownOutsideFocus callback.
7390TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007392 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7393 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007395 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007396
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007397 ASSERT_TRUE(mDispatcher->waitForIdle());
7398 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007399}
7400
7401// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7402// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7403TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007405 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007406 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007407 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007408
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007409 ASSERT_TRUE(mDispatcher->waitForIdle());
7410 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007411}
7412
7413// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7414// DOWN on the window that already has focus. Ensure no window received the
7415// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007416TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007418 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007419 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007421 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007422
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007423 ASSERT_TRUE(mDispatcher->waitForIdle());
7424 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007425}
7426
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007427// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7428// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7429TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7430 const MotionEvent event =
7431 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7432 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007433 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007434 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7435 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007437 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7438 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7439
7440 ASSERT_TRUE(mDispatcher->waitForIdle());
7441 mFakePolicy->assertOnPointerDownWasNotCalled();
7442 // Ensure that the unfocused window did not receive any FOCUS events.
7443 mUnfocusedWindow->assertNoEvents();
7444}
7445
chaviwaf87b3e2019-10-01 16:59:28 -07007446// These tests ensures we can send touch events to a single client when there are multiple input
7447// windows that point to the same client token.
7448class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7449 virtual void SetUp() override {
7450 InputDispatcherTest::SetUp();
7451
Chris Yea209fde2020-07-22 13:54:51 -07007452 std::shared_ptr<FakeApplicationHandle> application =
7453 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007454 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7455 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007456 mWindow1->setFrame(Rect(0, 0, 100, 100));
7457
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007458 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7459 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007460 mWindow2->setFrame(Rect(100, 100, 200, 200));
7461
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007462 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007463 }
7464
7465protected:
7466 sp<FakeWindowHandle> mWindow1;
7467 sp<FakeWindowHandle> mWindow2;
7468
7469 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007470 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007471 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7472 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007473 }
7474
7475 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7476 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007477 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007478 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007479
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007480 ASSERT_NE(nullptr, motionEvent)
7481 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007482
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007483 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007484 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007485
7486 for (size_t i = 0; i < points.size(); i++) {
7487 float expectedX = points[i].x;
7488 float expectedY = points[i].y;
7489
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007490 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007491 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007492 << ", got " << motionEvent->getX(i);
7493 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007494 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007495 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007496 }
7497 }
chaviw9eaa22c2020-07-01 16:21:27 -07007498
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007499 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007500 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007501 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7502 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007503
7504 // Always consume from window1 since it's the window that has the InputReceiver
7505 consumeMotionEvent(mWindow1, action, expectedPoints);
7506 }
chaviwaf87b3e2019-10-01 16:59:28 -07007507};
7508
7509TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7510 // Touch Window 1
7511 PointF touchedPoint = {10, 10};
7512 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007513 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007514
7515 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007516 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007517
7518 // Touch Window 2
7519 touchedPoint = {150, 150};
7520 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007521 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007522}
7523
chaviw9eaa22c2020-07-01 16:21:27 -07007524TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7525 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007526 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007527 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007528
7529 // Touch Window 1
7530 PointF touchedPoint = {10, 10};
7531 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007532 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007533 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007534 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007535
7536 // Touch Window 2
7537 touchedPoint = {150, 150};
7538 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007539 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7540 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007541
chaviw9eaa22c2020-07-01 16:21:27 -07007542 // Update the transform so rotation is set
7543 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007544 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007545 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7546 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007547}
7548
chaviw9eaa22c2020-07-01 16:21:27 -07007549TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007550 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007551 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007552
7553 // Touch Window 1
7554 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7555 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007556 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007557
7558 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007559 touchedPoints.push_back(PointF{150, 150});
7560 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007561 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007562
chaviw9eaa22c2020-07-01 16:21:27 -07007563 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007564 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007565 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007566
chaviw9eaa22c2020-07-01 16:21:27 -07007567 // Update the transform so rotation is set for Window 2
7568 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007569 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007570 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007571 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007572}
7573
chaviw9eaa22c2020-07-01 16:21:27 -07007574TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007575 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007576 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007577
7578 // Touch Window 1
7579 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7580 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007581 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007582
7583 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007584 touchedPoints.push_back(PointF{150, 150});
7585 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007586
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007587 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007588
7589 // Move both windows
7590 touchedPoints = {{20, 20}, {175, 175}};
7591 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7592 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7593
chaviw9eaa22c2020-07-01 16:21:27 -07007594 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007595
chaviw9eaa22c2020-07-01 16:21:27 -07007596 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007597 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007598 expectedPoints.pop_back();
7599
7600 // Touch Window 2
7601 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007602 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007603 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007604 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007605
7606 // Move both windows
7607 touchedPoints = {{20, 20}, {175, 175}};
7608 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7609 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7610
7611 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007612}
7613
7614TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7615 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007616 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007617
7618 // Touch Window 1
7619 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7620 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007621 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007622
7623 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007624 touchedPoints.push_back(PointF{150, 150});
7625 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007626
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007627 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007628
7629 // Move both windows
7630 touchedPoints = {{20, 20}, {175, 175}};
7631 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7632 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7633
chaviw9eaa22c2020-07-01 16:21:27 -07007634 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007635}
7636
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007637/**
7638 * When one of the windows is slippery, the touch should not slip into the other window with the
7639 * same input channel.
7640 */
7641TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7642 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007643 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007644
7645 // Touch down in window 1
7646 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7647 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7648 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7649
7650 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7651 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7652 // getting generated.
7653 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7654 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7655
7656 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7657}
7658
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007659/**
7660 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7661 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7662 * that the pointer is hovering over may have a different transform.
7663 */
7664TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007665 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007666
7667 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7669 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7670 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007671 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7672 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007673 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7675 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7676 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007677 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7678 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7679 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7680}
7681
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007682class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7683 virtual void SetUp() override {
7684 InputDispatcherTest::SetUp();
7685
Chris Yea209fde2020-07-22 13:54:51 -07007686 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007687 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007688 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7689 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007690 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007691 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007692 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007693
7694 // Set focused application.
7695 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007697 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007698 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007699 mWindow->consumeFocusEvent(true);
7700 }
7701
7702 virtual void TearDown() override {
7703 InputDispatcherTest::TearDown();
7704 mWindow.clear();
7705 }
7706
7707protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007708 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007709 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007710 sp<FakeWindowHandle> mWindow;
7711 static constexpr PointF WINDOW_LOCATION = {20, 20};
7712
7713 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007716 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007718 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007719 WINDOW_LOCATION));
7720 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007721
7722 sp<FakeWindowHandle> addSpyWindow() {
7723 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007724 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007725 spy->setTrustedOverlay(true);
7726 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007727 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007728 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007729 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007730 return spy;
7731 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007732};
7733
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007734// Send a tap and respond, which should not cause an ANR.
7735TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7736 tapOnWindow();
7737 mWindow->consumeMotionDown();
7738 mWindow->consumeMotionUp();
7739 ASSERT_TRUE(mDispatcher->waitForIdle());
7740 mFakePolicy->assertNotifyAnrWasNotCalled();
7741}
7742
7743// Send a regular key and respond, which should not cause an ANR.
7744TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007746 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7747 ASSERT_TRUE(mDispatcher->waitForIdle());
7748 mFakePolicy->assertNotifyAnrWasNotCalled();
7749}
7750
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007751TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7752 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007753 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007754 mWindow->consumeFocusEvent(false);
7755
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007756 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007757 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7758 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007759 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007761 // Key will not go to window because we have no focused window.
7762 // The 'no focused window' ANR timer should start instead.
7763
7764 // Now, the focused application goes away.
7765 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7766 // The key should get dropped and there should be no ANR.
7767
7768 ASSERT_TRUE(mDispatcher->waitForIdle());
7769 mFakePolicy->assertNotifyAnrWasNotCalled();
7770}
7771
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007772// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007773// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7774// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007775TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007778 WINDOW_LOCATION));
7779
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007780 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7781 ASSERT_TRUE(sequenceNum);
7782 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007783 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007785 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007786 mWindow->consumeMotionEvent(
7787 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007788 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007789 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007790}
7791
7792// Send a key to the app and have the app not respond right away.
7793TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7794 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007796 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7797 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007798 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007799 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007800 ASSERT_TRUE(mDispatcher->waitForIdle());
7801}
7802
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007803// We have a focused application, but no focused window
7804TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007805 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007806 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007807 mWindow->consumeFocusEvent(false);
7808
7809 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007811 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007812 WINDOW_LOCATION));
7813 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7814 mDispatcher->waitForIdle();
7815 mFakePolicy->assertNotifyAnrWasNotCalled();
7816
7817 // Once a focused event arrives, we get an ANR for this application
7818 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7819 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007820 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007821 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007822 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007823 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007825 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007826 ASSERT_TRUE(mDispatcher->waitForIdle());
7827}
7828
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007829/**
7830 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7831 * there will not be an ANR.
7832 */
7833TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7834 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007835 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007836 mWindow->consumeFocusEvent(false);
7837
7838 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007839 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7840 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007841 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7842 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7843
7844 // Define a valid key down event that is stale (too old).
7845 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007846 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007847 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007848
7849 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7850
7851 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007852 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007853 InputEventInjectionSync::WAIT_FOR_RESULT,
7854 INJECT_EVENT_TIMEOUT, policyFlags);
7855 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7856 << "Injection should fail because the event is stale";
7857
7858 ASSERT_TRUE(mDispatcher->waitForIdle());
7859 mFakePolicy->assertNotifyAnrWasNotCalled();
7860 mWindow->assertNoEvents();
7861}
7862
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007863// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007864// Make sure that we don't notify policy twice about the same ANR.
7865TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007866 const std::chrono::duration appTimeout = 400ms;
7867 mApplication->setDispatchingTimeout(appTimeout);
7868 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7869
Vishnu Nair47074b82020-08-14 11:54:47 -07007870 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007871 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007872 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007873
7874 // Once a focused event arrives, we get an ANR for this application
7875 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7876 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007877 const std::chrono::duration eventInjectionTimeout = 100ms;
7878 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007879 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007880 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007881 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7882 /*allowKeyRepeat=*/false);
7883 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7884 << "result=" << ftl::enum_string(result);
7885 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7886 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7887 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7888 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007889
Vishnu Naire4df8752022-09-08 09:17:55 -07007890 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007891 // ANR should not be raised again. It is up to policy to do that if it desires.
7892 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007893
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007894 // If we now get a focused window, the ANR should stop, but the policy handles that via
7895 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007896 ASSERT_TRUE(mDispatcher->waitForIdle());
7897}
7898
7899// We have a focused application, but no focused window
7900TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007901 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007902 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007903 mWindow->consumeFocusEvent(false);
7904
7905 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007906 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007907
Vishnu Naire4df8752022-09-08 09:17:55 -07007908 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7909 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007910
7911 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007912 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007913 ASSERT_TRUE(mDispatcher->waitForIdle());
7914 mWindow->assertNoEvents();
7915}
7916
7917/**
7918 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7919 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7920 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7921 * the ANR mechanism should still work.
7922 *
7923 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7924 * DOWN event, while not responding on the second one.
7925 */
7926TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7927 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007928 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007929 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7930 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7931 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007932 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007933
7934 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007935 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7937 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7938 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007939 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007940
7941 // We have now sent down and up. Let's consume first event and then ANR on the second.
7942 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7943 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007944 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007945}
7946
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007947// A spy window can receive an ANR
7948TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7949 sp<FakeWindowHandle> spy = addSpyWindow();
7950
7951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007952 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007953 WINDOW_LOCATION));
7954 mWindow->consumeMotionDown();
7955
7956 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7957 ASSERT_TRUE(sequenceNum);
7958 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007959 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007960
7961 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007962 spy->consumeMotionEvent(
7963 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007964 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007965 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007966}
7967
7968// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007969// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007970TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7971 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007972
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007974 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007975 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007977
7978 // Stuck on the ACTION_UP
7979 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007980 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007981
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007982 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007983 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007984 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7985 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007986
7987 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7988 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007989 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007990 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007991 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007992}
7993
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007994// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007995// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007996TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7997 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007998
7999 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008000 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8001 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008002
8003 mWindow->consumeMotionDown();
8004 // Stuck on the ACTION_UP
8005 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008006 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008007
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008008 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008009 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008010 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8011 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008012
8013 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8014 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008015 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008016 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008017 spy->assertNoEvents();
8018}
8019
8020TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008021 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008022
Prabir Pradhanfb549072023-10-05 19:17:36 +00008023 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008024
8025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008026 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008027 WINDOW_LOCATION));
8028
8029 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8030 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8031 ASSERT_TRUE(consumeSeq);
8032
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008033 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8034 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008035
8036 monitor.finishEvent(*consumeSeq);
8037 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8038
8039 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008040 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008041}
8042
8043// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8044// process events, you don't get an anr. When the window later becomes unresponsive again, you
8045// get an ANR again.
8046// 1. tap -> block on ACTION_UP -> receive ANR
8047// 2. consume all pending events (= queue becomes healthy again)
8048// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8049TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8050 tapOnWindow();
8051
8052 mWindow->consumeMotionDown();
8053 // Block on ACTION_UP
8054 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008055 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008056 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8057 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008058 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008059 mWindow->assertNoEvents();
8060
8061 tapOnWindow();
8062 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008063 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008064 mWindow->consumeMotionUp();
8065
8066 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008067 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008068 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008069 mWindow->assertNoEvents();
8070}
8071
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008072// If a connection remains unresponsive for a while, make sure policy is only notified once about
8073// it.
8074TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008077 WINDOW_LOCATION));
8078
8079 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008080 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008081 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008082 // 'notifyConnectionUnresponsive' should only be called once per connection
8083 mFakePolicy->assertNotifyAnrWasNotCalled();
8084 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008085 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008086 mWindow->consumeMotionEvent(
8087 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008088 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008089 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008090 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008091 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008092}
8093
8094/**
8095 * 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 -07008096 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008097 *
8098 * Warning!!!
8099 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8100 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008101 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008102 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8103 *
8104 * If that value changes, this test should also change.
8105 */
8106TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8107 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008108 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008109
8110 tapOnWindow();
8111 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8112 ASSERT_TRUE(downSequenceNum);
8113 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8114 ASSERT_TRUE(upSequenceNum);
8115 // Don't finish the events yet, and send a key
8116 // Injection will "succeed" because we will eventually give up and send the key to the focused
8117 // window even if motions are still being processed. But because the injection timeout is short,
8118 // we will receive INJECTION_TIMED_OUT as the result.
8119
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008120 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008121 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8122 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008123 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008124 // Key will not be sent to the window, yet, because the window is still processing events
8125 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008126 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8127 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8128 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8129 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008130
8131 std::this_thread::sleep_for(500ms);
8132 // if we wait long enough though, dispatcher will give up, and still send the key
8133 // to the focused window, even though we have not yet finished the motion event
8134 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8135 mWindow->finishEvent(*downSequenceNum);
8136 mWindow->finishEvent(*upSequenceNum);
8137}
8138
8139/**
8140 * If a window is processing a motion event, and then a key event comes in, the key event should
8141 * not go to the focused window until the motion is processed.
8142 * If then a new motion comes in, then the pending key event should be going to the currently
8143 * focused window right away.
8144 */
8145TEST_F(InputDispatcherSingleWindowAnr,
8146 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8147 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008148 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008149
8150 tapOnWindow();
8151 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8152 ASSERT_TRUE(downSequenceNum);
8153 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8154 ASSERT_TRUE(upSequenceNum);
8155 // Don't finish the events yet, and send a key
8156 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008158 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8159 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008160 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008161 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8162 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8163 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8164 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008165
8166 // Now tap down again. It should cause the pending key to go to the focused window right away.
8167 tapOnWindow();
8168 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
8169 // the other events yet. We can finish events in any order.
8170 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8171 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
8172 mWindow->consumeMotionDown();
8173 mWindow->consumeMotionUp();
8174 mWindow->assertNoEvents();
8175}
8176
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008177/**
8178 * Send an event to the app and have the app not respond right away.
8179 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8180 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8181 * At some point, the window becomes responsive again.
8182 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8183 */
8184TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8185 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8186 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8187 .build());
8188
8189 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8190 ASSERT_TRUE(sequenceNum);
8191 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8192 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8193
8194 mWindow->finishEvent(*sequenceNum);
8195 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8196 ASSERT_TRUE(mDispatcher->waitForIdle());
8197 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8198
8199 // Now that the window is responsive, let's continue the gesture.
8200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8201 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8202 .build());
8203
8204 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8205 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8206 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8207 .build());
8208
8209 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8210 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8211 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8212 .build());
8213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8214 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8215 .build());
8216 // We already canceled this pointer, so the window shouldn't get any new events.
8217 mWindow->assertNoEvents();
8218
8219 // Start another one.
8220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8221 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8222 .build());
8223 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8224}
8225
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008226class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8227 virtual void SetUp() override {
8228 InputDispatcherTest::SetUp();
8229
Chris Yea209fde2020-07-22 13:54:51 -07008230 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008231 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008232 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8233 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008234 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008235 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008236 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008237
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008238 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8239 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008240 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008241 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008242
8243 // Set focused application.
8244 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008245 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008246
8247 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008248 mDispatcher->onWindowInfosChanged(
8249 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008250 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008251 mFocusedWindow->consumeFocusEvent(true);
8252 }
8253
8254 virtual void TearDown() override {
8255 InputDispatcherTest::TearDown();
8256
8257 mUnfocusedWindow.clear();
8258 mFocusedWindow.clear();
8259 }
8260
8261protected:
Chris Yea209fde2020-07-22 13:54:51 -07008262 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008263 sp<FakeWindowHandle> mUnfocusedWindow;
8264 sp<FakeWindowHandle> mFocusedWindow;
8265 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8266 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8267 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8268
8269 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8270
8271 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8272
8273private:
8274 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008276 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008277 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008279 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280 location));
8281 }
8282};
8283
8284// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8285// should be ANR'd first.
8286TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008288 injectMotionEvent(*mDispatcher,
8289 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8290 AINPUT_SOURCE_TOUCHSCREEN)
8291 .pointer(PointerBuilder(0, ToolType::FINGER)
8292 .x(FOCUSED_WINDOW_LOCATION.x)
8293 .y(FOCUSED_WINDOW_LOCATION.y))
8294 .build()));
8295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8296 injectMotionEvent(*mDispatcher,
8297 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8298 AINPUT_SOURCE_TOUCHSCREEN)
8299 .pointer(PointerBuilder(0, ToolType::FINGER)
8300 .x(FOCUSED_WINDOW_LOCATION.x)
8301 .y(FOCUSED_WINDOW_LOCATION.y))
8302 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008303 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008304 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008305 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008306 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008307 // We consumed all events, so no ANR
8308 ASSERT_TRUE(mDispatcher->waitForIdle());
8309 mFakePolicy->assertNotifyAnrWasNotCalled();
8310
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008312 injectMotionEvent(*mDispatcher,
8313 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8314 AINPUT_SOURCE_TOUCHSCREEN)
8315 .pointer(PointerBuilder(0, ToolType::FINGER)
8316 .x(FOCUSED_WINDOW_LOCATION.x)
8317 .y(FOCUSED_WINDOW_LOCATION.y))
8318 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008319 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8320 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008321
8322 const std::chrono::duration timeout =
8323 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008324 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008325
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008326 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008327 mFocusedWindow->consumeMotionDown();
8328 // This cancel is generated because the connection was unresponsive
8329 mFocusedWindow->consumeMotionCancel();
8330 mFocusedWindow->assertNoEvents();
8331 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008332 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008333 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8334 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008335 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008336}
8337
8338// If we have 2 windows with identical timeouts that are both unresponsive,
8339// it doesn't matter which order they should have ANR.
8340// But we should receive ANR for both.
8341TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8342 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008343 mUnfocusedWindow->setDispatchingTimeout(
8344 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008345 mDispatcher->onWindowInfosChanged(
8346 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008347
8348 tapOnFocusedWindow();
8349 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008350 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008351 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8352 mFocusedWindow->getDispatchingTimeout(
8353 DISPATCHING_TIMEOUT)),
8354 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8355
8356 ASSERT_THAT(anrConnectionTokens,
8357 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8358 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008359
8360 ASSERT_TRUE(mDispatcher->waitForIdle());
8361 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008362
8363 mFocusedWindow->consumeMotionDown();
8364 mFocusedWindow->consumeMotionUp();
8365 mUnfocusedWindow->consumeMotionOutside();
8366
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008367 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8368 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008369
8370 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008371 ASSERT_THAT(responsiveTokens,
8372 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8373 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008374 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008375}
8376
8377// If a window is already not responding, the second tap on the same window should be ignored.
8378// We should also log an error to account for the dropped event (not tested here).
8379// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8380TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8381 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008382 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008383 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008384 // Receive the events, but don't respond
8385 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8386 ASSERT_TRUE(downEventSequenceNum);
8387 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8388 ASSERT_TRUE(upEventSequenceNum);
8389 const std::chrono::duration timeout =
8390 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008391 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008392
8393 // Tap once again
8394 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008395 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008398 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008399 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008400 FOCUSED_WINDOW_LOCATION));
8401 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8402 // valid touch target
8403 mUnfocusedWindow->assertNoEvents();
8404
8405 // Consume the first tap
8406 mFocusedWindow->finishEvent(*downEventSequenceNum);
8407 mFocusedWindow->finishEvent(*upEventSequenceNum);
8408 ASSERT_TRUE(mDispatcher->waitForIdle());
8409 // The second tap did not go to the focused window
8410 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008411 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008412 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8413 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008414 mFakePolicy->assertNotifyAnrWasNotCalled();
8415}
8416
8417// If you tap outside of all windows, there will not be ANR
8418TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008419 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008421 LOCATION_OUTSIDE_ALL_WINDOWS));
8422 ASSERT_TRUE(mDispatcher->waitForIdle());
8423 mFakePolicy->assertNotifyAnrWasNotCalled();
8424}
8425
8426// Since the focused window is paused, tapping on it should not produce any events
8427TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8428 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008429 mDispatcher->onWindowInfosChanged(
8430 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008431
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008432 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008434 FOCUSED_WINDOW_LOCATION));
8435
8436 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8437 ASSERT_TRUE(mDispatcher->waitForIdle());
8438 // Should not ANR because the window is paused, and touches shouldn't go to it
8439 mFakePolicy->assertNotifyAnrWasNotCalled();
8440
8441 mFocusedWindow->assertNoEvents();
8442 mUnfocusedWindow->assertNoEvents();
8443}
8444
8445/**
8446 * 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 -07008447 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008448 * If a different window becomes focused at this time, the key should go to that window instead.
8449 *
8450 * Warning!!!
8451 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8452 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008453 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008454 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8455 *
8456 * If that value changes, this test should also change.
8457 */
8458TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8459 // Set a long ANR timeout to prevent it from triggering
8460 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008461 mDispatcher->onWindowInfosChanged(
8462 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008463
8464 tapOnUnfocusedWindow();
8465 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8466 ASSERT_TRUE(downSequenceNum);
8467 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8468 ASSERT_TRUE(upSequenceNum);
8469 // Don't finish the events yet, and send a key
8470 // Injection will succeed because we will eventually give up and send the key to the focused
8471 // window even if motions are still being processed.
8472
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008473 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008474 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8475 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008477 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008478 // and the key remains pending, waiting for the touch events to be processed.
8479 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8480 // under the hood.
8481 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8482 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008483
8484 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008485 mFocusedWindow->setFocusable(false);
8486 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008487 mDispatcher->onWindowInfosChanged(
8488 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008489 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008490
8491 // Focus events should precede the key events
8492 mUnfocusedWindow->consumeFocusEvent(true);
8493 mFocusedWindow->consumeFocusEvent(false);
8494
8495 // Finish the tap events, which should unblock dispatcher
8496 mUnfocusedWindow->finishEvent(*downSequenceNum);
8497 mUnfocusedWindow->finishEvent(*upSequenceNum);
8498
8499 // Now that all queues are cleared and no backlog in the connections, the key event
8500 // can finally go to the newly focused "mUnfocusedWindow".
8501 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8502 mFocusedWindow->assertNoEvents();
8503 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008504 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008505}
8506
8507// When the touch stream is split across 2 windows, and one of them does not respond,
8508// then ANR should be raised and the touch should be canceled for the unresponsive window.
8509// The other window should not be affected by that.
8510TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8511 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8513 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8514 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008515 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008516 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517
8518 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008519 mDispatcher->notifyMotion(
8520 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8521 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008522
8523 const std::chrono::duration timeout =
8524 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008525 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008526
8527 mUnfocusedWindow->consumeMotionDown();
8528 mFocusedWindow->consumeMotionDown();
8529 // Focused window may or may not receive ACTION_MOVE
8530 // But it should definitely receive ACTION_CANCEL due to the ANR
8531 InputEvent* event;
8532 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8533 ASSERT_TRUE(moveOrCancelSequenceNum);
8534 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8535 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008536 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008537 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8538 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8539 mFocusedWindow->consumeMotionCancel();
8540 } else {
8541 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8542 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008543 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008544 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8545 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008546
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008547 mUnfocusedWindow->assertNoEvents();
8548 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008549 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008550}
8551
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008552/**
8553 * If we have no focused window, and a key comes in, we start the ANR timer.
8554 * The focused application should add a focused window before the timer runs out to prevent ANR.
8555 *
8556 * If the user touches another application during this time, the key should be dropped.
8557 * Next, if a new focused window comes in, without toggling the focused application,
8558 * then no ANR should occur.
8559 *
8560 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8561 * but in some cases the policy may not update the focused application.
8562 */
8563TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8564 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8565 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008566 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008567 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8568 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8569 mFocusedWindow->setFocusable(false);
8570
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008571 mDispatcher->onWindowInfosChanged(
8572 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008573 mFocusedWindow->consumeFocusEvent(false);
8574
8575 // Send a key. The ANR timer should start because there is no focused window.
8576 // 'focusedApplication' will get blamed if this timer completes.
8577 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008578 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008579 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8580 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008581 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008583
8584 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8585 // then the injected touches won't cause the focused event to get dropped.
8586 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8587 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8588 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8589 // For this test, it means that the key would get delivered to the window once it becomes
8590 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008591 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008592
8593 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008594 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8595 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8596 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008597
8598 // We do not consume the motion right away, because that would require dispatcher to first
8599 // process (== drop) the key event, and by that time, ANR will be raised.
8600 // Set the focused window first.
8601 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008602 mDispatcher->onWindowInfosChanged(
8603 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008604 setFocusedWindow(mFocusedWindow);
8605 mFocusedWindow->consumeFocusEvent(true);
8606 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8607 // to another application. This could be a bug / behaviour in the policy.
8608
8609 mUnfocusedWindow->consumeMotionDown();
8610
8611 ASSERT_TRUE(mDispatcher->waitForIdle());
8612 // Should not ANR because we actually have a focused window. It was just added too slowly.
8613 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8614}
8615
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008616// These tests ensure we cannot send touch events to a window that's positioned behind a window
8617// that has feature NO_INPUT_CHANNEL.
8618// Layout:
8619// Top (closest to user)
8620// mNoInputWindow (above all windows)
8621// mBottomWindow
8622// Bottom (furthest from user)
8623class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8624 virtual void SetUp() override {
8625 InputDispatcherTest::SetUp();
8626
8627 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008628 mNoInputWindow =
8629 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8630 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008631 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008632 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008633 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8634 // It's perfectly valid for this window to not have an associated input channel
8635
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008636 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8637 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008638 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8639
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008640 mDispatcher->onWindowInfosChanged(
8641 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008642 }
8643
8644protected:
8645 std::shared_ptr<FakeApplicationHandle> mApplication;
8646 sp<FakeWindowHandle> mNoInputWindow;
8647 sp<FakeWindowHandle> mBottomWindow;
8648};
8649
8650TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8651 PointF touchedPoint = {10, 10};
8652
Prabir Pradhan678438e2023-04-13 19:32:51 +00008653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8654 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8655 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008656
8657 mNoInputWindow->assertNoEvents();
8658 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8659 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8660 // and therefore should prevent mBottomWindow from receiving touches
8661 mBottomWindow->assertNoEvents();
8662}
8663
8664/**
8665 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8666 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8667 */
8668TEST_F(InputDispatcherMultiWindowOcclusionTests,
8669 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008670 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8671 "Window with input channel and NO_INPUT_CHANNEL",
8672 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008673
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008674 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008675 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008676 mDispatcher->onWindowInfosChanged(
8677 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008678
8679 PointF touchedPoint = {10, 10};
8680
Prabir Pradhan678438e2023-04-13 19:32:51 +00008681 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8682 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8683 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008684
8685 mNoInputWindow->assertNoEvents();
8686 mBottomWindow->assertNoEvents();
8687}
8688
Vishnu Nair958da932020-08-21 17:12:37 -07008689class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8690protected:
8691 std::shared_ptr<FakeApplicationHandle> mApp;
8692 sp<FakeWindowHandle> mWindow;
8693 sp<FakeWindowHandle> mMirror;
8694
8695 virtual void SetUp() override {
8696 InputDispatcherTest::SetUp();
8697 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008698 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8699 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8700 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008701 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8702 mWindow->setFocusable(true);
8703 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008704 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008705 }
8706};
8707
8708TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8709 // Request focus on a mirrored window
8710 setFocusedWindow(mMirror);
8711
8712 // window gets focused
8713 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008715 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008716 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8717}
8718
8719// A focused & mirrored window remains focused only if the window and its mirror are both
8720// focusable.
8721TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8722 setFocusedWindow(mMirror);
8723
8724 // window gets focused
8725 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008727 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008728 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008730 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008731 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8732
8733 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008734 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008735
8736 // window loses focus since one of the windows associated with the token in not focusable
8737 mWindow->consumeFocusEvent(false);
8738
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008739 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008740 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008741 mWindow->assertNoEvents();
8742}
8743
8744// A focused & mirrored window remains focused until the window and its mirror both become
8745// invisible.
8746TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8747 setFocusedWindow(mMirror);
8748
8749 // window gets focused
8750 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008752 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008753 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008756 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8757
8758 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008759 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008760
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008762 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008763 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008765 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008766 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8767
8768 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008769 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008770
8771 // window loses focus only after all windows associated with the token become invisible.
8772 mWindow->consumeFocusEvent(false);
8773
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008774 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008775 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008776 mWindow->assertNoEvents();
8777}
8778
8779// A focused & mirrored window remains focused until both windows are removed.
8780TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8781 setFocusedWindow(mMirror);
8782
8783 // window gets focused
8784 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008786 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008787 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008789 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008790 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8791
8792 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008793 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008794
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008796 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008797 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008799 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008800 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8801
8802 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008803 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008804 mWindow->consumeFocusEvent(false);
8805
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008806 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008807 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008808 mWindow->assertNoEvents();
8809}
8810
8811// Focus request can be pending until one window becomes visible.
8812TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8813 // Request focus on an invisible mirror.
8814 mWindow->setVisible(false);
8815 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008817 setFocusedWindow(mMirror);
8818
8819 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008821 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8822 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008823
8824 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008825 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008826
8827 // window gets focused
8828 mWindow->consumeFocusEvent(true);
8829 // window gets the pending key event
8830 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8831}
Prabir Pradhan99987712020-11-10 18:43:05 -08008832
8833class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8834protected:
8835 std::shared_ptr<FakeApplicationHandle> mApp;
8836 sp<FakeWindowHandle> mWindow;
8837 sp<FakeWindowHandle> mSecondWindow;
8838
8839 void SetUp() override {
8840 InputDispatcherTest::SetUp();
8841 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008842 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008843 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008844 mSecondWindow =
8845 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008846 mSecondWindow->setFocusable(true);
8847
8848 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008849 mDispatcher->onWindowInfosChanged(
8850 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008851
8852 setFocusedWindow(mWindow);
8853 mWindow->consumeFocusEvent(true);
8854 }
8855
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008856 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008857 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008858 }
8859
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008860 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8861 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008862 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008863 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8864 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008865 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008866 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008867 }
8868};
8869
8870TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8871 // Ensure that capture cannot be obtained for unfocused windows.
8872 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8873 mFakePolicy->assertSetPointerCaptureNotCalled();
8874 mSecondWindow->assertNoEvents();
8875
8876 // Ensure that capture can be enabled from the focus window.
8877 requestAndVerifyPointerCapture(mWindow, true);
8878
8879 // Ensure that capture cannot be disabled from a window that does not have capture.
8880 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8881 mFakePolicy->assertSetPointerCaptureNotCalled();
8882
8883 // Ensure that capture can be disabled from the window with capture.
8884 requestAndVerifyPointerCapture(mWindow, false);
8885}
8886
8887TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008888 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008889
8890 setFocusedWindow(mSecondWindow);
8891
8892 // Ensure that the capture disabled event was sent first.
8893 mWindow->consumeCaptureEvent(false);
8894 mWindow->consumeFocusEvent(false);
8895 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008896 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008897
8898 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008899 notifyPointerCaptureChanged({});
8900 notifyPointerCaptureChanged(request);
8901 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008902 mWindow->assertNoEvents();
8903 mSecondWindow->assertNoEvents();
8904 mFakePolicy->assertSetPointerCaptureNotCalled();
8905}
8906
8907TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008908 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008909
8910 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008911 notifyPointerCaptureChanged({});
8912 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008913
8914 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008915 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008916 mWindow->consumeCaptureEvent(false);
8917 mWindow->assertNoEvents();
8918}
8919
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008920TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8921 requestAndVerifyPointerCapture(mWindow, true);
8922
8923 // The first window loses focus.
8924 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008925 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008926 mWindow->consumeCaptureEvent(false);
8927
8928 // Request Pointer Capture from the second window before the notification from InputReader
8929 // arrives.
8930 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008931 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008932
8933 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008934 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008935
8936 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008937 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008938
8939 mSecondWindow->consumeFocusEvent(true);
8940 mSecondWindow->consumeCaptureEvent(true);
8941}
8942
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008943TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8944 // App repeatedly enables and disables capture.
8945 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8946 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8947 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8948 mFakePolicy->assertSetPointerCaptureCalled(false);
8949 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8950 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8951
8952 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8953 // first request is now stale, this should do nothing.
8954 notifyPointerCaptureChanged(firstRequest);
8955 mWindow->assertNoEvents();
8956
8957 // InputReader notifies that the second request was enabled.
8958 notifyPointerCaptureChanged(secondRequest);
8959 mWindow->consumeCaptureEvent(true);
8960}
8961
Prabir Pradhan7092e262022-05-03 16:51:09 +00008962TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8963 requestAndVerifyPointerCapture(mWindow, true);
8964
8965 // App toggles pointer capture off and on.
8966 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8967 mFakePolicy->assertSetPointerCaptureCalled(false);
8968
8969 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8970 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8971
8972 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8973 // preceding "disable" request.
8974 notifyPointerCaptureChanged(enableRequest);
8975
8976 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8977 // any notifications.
8978 mWindow->assertNoEvents();
8979}
8980
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008981/**
8982 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8983 * mouse movements don't affect the previous mouse hovering state.
8984 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8985 * HOVER_MOVE events).
8986 */
8987TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8988 // Mouse hover on the window
8989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8990 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8991 .build());
8992 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8993 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8994 .build());
8995
8996 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8997 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8998
8999 // Start pointer capture
9000 requestAndVerifyPointerCapture(mWindow, true);
9001
9002 // Send some relative mouse movements and receive them in the window.
9003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9004 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9005 .build());
9006 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9007 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9008
9009 // Stop pointer capture
9010 requestAndVerifyPointerCapture(mWindow, false);
9011
9012 // Continue hovering on the window
9013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9014 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9015 .build());
9016 mWindow->consumeMotionEvent(
9017 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9018
9019 mWindow->assertNoEvents();
9020}
9021
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009022class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9023protected:
9024 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009025
9026 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9027 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9028
9029 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9030 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9031
9032 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9033 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9034 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9035 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9036 MAXIMUM_OBSCURING_OPACITY);
9037
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009038 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9039 static constexpr gui::Uid APP_B_UID{10002};
9040 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009041
9042 sp<FakeWindowHandle> mTouchWindow;
9043
9044 virtual void SetUp() override {
9045 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009046 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009047 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9048 }
9049
9050 virtual void TearDown() override {
9051 InputDispatcherTest::TearDown();
9052 mTouchWindow.clear();
9053 }
9054
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009055 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009056 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009057 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009058 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009059 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009060 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009061 return window;
9062 }
9063
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009064 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009065 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9066 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009067 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009068 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009069 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009070 return window;
9071 }
9072
9073 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009074 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9075 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9076 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009077 }
9078};
9079
9080TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009081 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009082 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009083 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009084
9085 touch();
9086
9087 mTouchWindow->assertNoEvents();
9088}
9089
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009090TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009091 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9092 const sp<FakeWindowHandle>& w =
9093 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009094 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009095
9096 touch();
9097
9098 mTouchWindow->assertNoEvents();
9099}
9100
9101TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009102 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9103 const sp<FakeWindowHandle>& w =
9104 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009105 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009106
9107 touch();
9108
9109 w->assertNoEvents();
9110}
9111
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009112TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009113 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009114 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009115
9116 touch();
9117
9118 mTouchWindow->consumeAnyMotionDown();
9119}
9120
9121TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009122 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009123 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009124 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009125 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009126
9127 touch({PointF{100, 100}});
9128
9129 mTouchWindow->consumeAnyMotionDown();
9130}
9131
9132TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009133 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009134 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009135 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009136
9137 touch();
9138
9139 mTouchWindow->consumeAnyMotionDown();
9140}
9141
9142TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9143 const sp<FakeWindowHandle>& w =
9144 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009145 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009146
9147 touch();
9148
9149 mTouchWindow->consumeAnyMotionDown();
9150}
9151
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009152TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9153 const sp<FakeWindowHandle>& w =
9154 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009155 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009156
9157 touch();
9158
9159 w->assertNoEvents();
9160}
9161
9162/**
9163 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9164 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9165 * window, the occluding window will still receive ACTION_OUTSIDE event.
9166 */
9167TEST_F(InputDispatcherUntrustedTouchesTest,
9168 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9169 const sp<FakeWindowHandle>& w =
9170 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009171 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009172 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009173
9174 touch();
9175
9176 w->consumeMotionOutside();
9177}
9178
9179TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9180 const sp<FakeWindowHandle>& w =
9181 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009182 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009183 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009184
9185 touch();
9186
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009187 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009188}
9189
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009190TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009191 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009192 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9193 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009194 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009195
9196 touch();
9197
9198 mTouchWindow->consumeAnyMotionDown();
9199}
9200
9201TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9202 const sp<FakeWindowHandle>& w =
9203 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9204 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009205 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009206
9207 touch();
9208
9209 mTouchWindow->consumeAnyMotionDown();
9210}
9211
9212TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009213 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009214 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9215 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009216 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009217
9218 touch();
9219
9220 mTouchWindow->assertNoEvents();
9221}
9222
9223TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9224 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9225 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009226 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9227 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009228 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009229 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9230 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009231 mDispatcher->onWindowInfosChanged(
9232 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009233
9234 touch();
9235
9236 mTouchWindow->assertNoEvents();
9237}
9238
9239TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9240 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9241 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009242 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9243 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009244 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009245 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9246 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009247 mDispatcher->onWindowInfosChanged(
9248 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009249
9250 touch();
9251
9252 mTouchWindow->consumeAnyMotionDown();
9253}
9254
9255TEST_F(InputDispatcherUntrustedTouchesTest,
9256 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9257 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009258 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9259 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009260 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009261 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9262 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009263 mDispatcher->onWindowInfosChanged(
9264 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009265
9266 touch();
9267
9268 mTouchWindow->consumeAnyMotionDown();
9269}
9270
9271TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9272 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009273 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9274 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009275 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009276 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9277 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009278 mDispatcher->onWindowInfosChanged(
9279 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009280
9281 touch();
9282
9283 mTouchWindow->assertNoEvents();
9284}
9285
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009286TEST_F(InputDispatcherUntrustedTouchesTest,
9287 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9288 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009289 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9290 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009291 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009292 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9293 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009294 mDispatcher->onWindowInfosChanged(
9295 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009296
9297 touch();
9298
9299 mTouchWindow->assertNoEvents();
9300}
9301
9302TEST_F(InputDispatcherUntrustedTouchesTest,
9303 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9304 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009305 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9306 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009307 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009308 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9309 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009310 mDispatcher->onWindowInfosChanged(
9311 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009312
9313 touch();
9314
9315 mTouchWindow->consumeAnyMotionDown();
9316}
9317
9318TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9319 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009320 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9321 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009322 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009323
9324 touch();
9325
9326 mTouchWindow->consumeAnyMotionDown();
9327}
9328
9329TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9330 const sp<FakeWindowHandle>& w =
9331 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009332 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009333
9334 touch();
9335
9336 mTouchWindow->consumeAnyMotionDown();
9337}
9338
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009339TEST_F(InputDispatcherUntrustedTouchesTest,
9340 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9341 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9342 const sp<FakeWindowHandle>& w =
9343 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009344 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009345
9346 touch();
9347
9348 mTouchWindow->assertNoEvents();
9349}
9350
9351TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9352 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9353 const sp<FakeWindowHandle>& w =
9354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009355 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009356
9357 touch();
9358
9359 mTouchWindow->consumeAnyMotionDown();
9360}
9361
9362TEST_F(InputDispatcherUntrustedTouchesTest,
9363 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9364 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9365 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009366 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9367 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009368 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009369
9370 touch();
9371
9372 mTouchWindow->consumeAnyMotionDown();
9373}
9374
9375TEST_F(InputDispatcherUntrustedTouchesTest,
9376 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9377 const sp<FakeWindowHandle>& w1 =
9378 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9379 OPACITY_BELOW_THRESHOLD);
9380 const sp<FakeWindowHandle>& w2 =
9381 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9382 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009383 mDispatcher->onWindowInfosChanged(
9384 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009385
9386 touch();
9387
9388 mTouchWindow->assertNoEvents();
9389}
9390
9391/**
9392 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9393 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9394 * (which alone would result in allowing touches) does not affect the blocking behavior.
9395 */
9396TEST_F(InputDispatcherUntrustedTouchesTest,
9397 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9398 const sp<FakeWindowHandle>& wB =
9399 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9400 OPACITY_BELOW_THRESHOLD);
9401 const sp<FakeWindowHandle>& wC =
9402 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9403 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009404 mDispatcher->onWindowInfosChanged(
9405 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009406
9407 touch();
9408
9409 mTouchWindow->assertNoEvents();
9410}
9411
9412/**
9413 * This test is testing that a window from a different UID but with same application token doesn't
9414 * block the touch. Apps can share the application token for close UI collaboration for example.
9415 */
9416TEST_F(InputDispatcherUntrustedTouchesTest,
9417 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9418 const sp<FakeWindowHandle>& w =
9419 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9420 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009421 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009422
9423 touch();
9424
9425 mTouchWindow->consumeAnyMotionDown();
9426}
9427
arthurhungb89ccb02020-12-30 16:19:01 +08009428class InputDispatcherDragTests : public InputDispatcherTest {
9429protected:
9430 std::shared_ptr<FakeApplicationHandle> mApp;
9431 sp<FakeWindowHandle> mWindow;
9432 sp<FakeWindowHandle> mSecondWindow;
9433 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009434 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009435 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9436 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009437
9438 void SetUp() override {
9439 InputDispatcherTest::SetUp();
9440 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009441 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009442 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009443
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009444 mSecondWindow =
9445 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009446 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009447
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009448 mSpyWindow =
9449 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009450 mSpyWindow->setSpy(true);
9451 mSpyWindow->setTrustedOverlay(true);
9452 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9453
arthurhungb89ccb02020-12-30 16:19:01 +08009454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009455 mDispatcher->onWindowInfosChanged(
9456 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9457 {},
9458 0,
9459 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009460 }
9461
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009462 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9463 switch (fromSource) {
9464 case AINPUT_SOURCE_TOUCHSCREEN:
9465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009466 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009467 ADISPLAY_ID_DEFAULT, {50, 50}))
9468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9469 break;
9470 case AINPUT_SOURCE_STYLUS:
9471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009472 injectMotionEvent(*mDispatcher,
9473 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9474 AINPUT_SOURCE_STYLUS)
9475 .buttonState(
9476 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9477 .pointer(PointerBuilder(0, ToolType::STYLUS)
9478 .x(50)
9479 .y(50))
9480 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009481 break;
9482 case AINPUT_SOURCE_MOUSE:
9483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009484 injectMotionEvent(*mDispatcher,
9485 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9486 AINPUT_SOURCE_MOUSE)
9487 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9488 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9489 ToolType::MOUSE)
9490 .x(50)
9491 .y(50))
9492 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009493 break;
9494 default:
9495 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9496 }
arthurhungb89ccb02020-12-30 16:19:01 +08009497
9498 // Window should receive motion event.
9499 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009500 // Spy window should also receive motion event
9501 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009502 }
9503
9504 // Start performing drag, we will create a drag window and transfer touch to it.
9505 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9506 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009507 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009508 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009509 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009510 }
arthurhungb89ccb02020-12-30 16:19:01 +08009511
9512 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009513 mDragWindow =
9514 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009515 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009516 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9517 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9518 {},
9519 0,
9520 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009521
9522 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009523 bool transferred =
9524 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009525 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009526 if (transferred) {
9527 mWindow->consumeMotionCancel();
9528 mDragWindow->consumeMotionDown();
9529 }
9530 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009531 }
9532};
9533
9534TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009535 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009536
9537 // Move on window.
9538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009539 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009540 ADISPLAY_ID_DEFAULT, {50, 50}))
9541 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9542 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9543 mWindow->consumeDragEvent(false, 50, 50);
9544 mSecondWindow->assertNoEvents();
9545
9546 // Move to another window.
9547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009548 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009549 ADISPLAY_ID_DEFAULT, {150, 50}))
9550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9551 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9552 mWindow->consumeDragEvent(true, 150, 50);
9553 mSecondWindow->consumeDragEvent(false, 50, 50);
9554
9555 // Move back to original window.
9556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009557 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009558 ADISPLAY_ID_DEFAULT, {50, 50}))
9559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9560 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9561 mWindow->consumeDragEvent(false, 50, 50);
9562 mSecondWindow->consumeDragEvent(true, -50, 50);
9563
9564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009565 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9566 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9568 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9569 mWindow->assertNoEvents();
9570 mSecondWindow->assertNoEvents();
9571}
9572
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009573TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009574 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009575
9576 // No cancel event after drag start
9577 mSpyWindow->assertNoEvents();
9578
9579 const MotionEvent secondFingerDownEvent =
9580 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9581 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009582 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9583 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009584 .build();
9585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009586 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009587 InputEventInjectionSync::WAIT_FOR_RESULT))
9588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9589
9590 // Receives cancel for first pointer after next pointer down
9591 mSpyWindow->consumeMotionCancel();
9592 mSpyWindow->consumeMotionDown();
9593
9594 mSpyWindow->assertNoEvents();
9595}
9596
arthurhungf452d0b2021-01-06 00:19:52 +08009597TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009598 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009599
9600 // Move on window.
9601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009602 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009603 ADISPLAY_ID_DEFAULT, {50, 50}))
9604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9605 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9606 mWindow->consumeDragEvent(false, 50, 50);
9607 mSecondWindow->assertNoEvents();
9608
9609 // Move to another window.
9610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009611 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009612 ADISPLAY_ID_DEFAULT, {150, 50}))
9613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9614 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9615 mWindow->consumeDragEvent(true, 150, 50);
9616 mSecondWindow->consumeDragEvent(false, 50, 50);
9617
9618 // drop to another window.
9619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009620 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009621 {150, 50}))
9622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9623 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009624 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009625 mWindow->assertNoEvents();
9626 mSecondWindow->assertNoEvents();
9627}
9628
arthurhung6d4bed92021-03-17 11:59:33 +08009629TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009630 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009631
9632 // Move on window and keep button pressed.
9633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009634 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009635 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9636 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009637 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009638 .build()))
9639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9640 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9641 mWindow->consumeDragEvent(false, 50, 50);
9642 mSecondWindow->assertNoEvents();
9643
9644 // Move to another window and release button, expect to drop item.
9645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009646 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009647 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9648 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009650 .build()))
9651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9652 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9653 mWindow->assertNoEvents();
9654 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009655 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009656
9657 // nothing to the window.
9658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009659 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009660 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9661 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009662 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009663 .build()))
9664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9665 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9666 mWindow->assertNoEvents();
9667 mSecondWindow->assertNoEvents();
9668}
9669
Arthur Hung54745652022-04-20 07:17:41 +00009670TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009671 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009672
9673 // Set second window invisible.
9674 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009675 mDispatcher->onWindowInfosChanged(
9676 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009677
9678 // Move on window.
9679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009680 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009681 ADISPLAY_ID_DEFAULT, {50, 50}))
9682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9683 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9684 mWindow->consumeDragEvent(false, 50, 50);
9685 mSecondWindow->assertNoEvents();
9686
9687 // Move to another window.
9688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009689 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009690 ADISPLAY_ID_DEFAULT, {150, 50}))
9691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9692 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9693 mWindow->consumeDragEvent(true, 150, 50);
9694 mSecondWindow->assertNoEvents();
9695
9696 // drop to another window.
9697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009698 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009699 {150, 50}))
9700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9701 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009702 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009703 mWindow->assertNoEvents();
9704 mSecondWindow->assertNoEvents();
9705}
9706
Arthur Hung54745652022-04-20 07:17:41 +00009707TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009708 // Ensure window could track pointerIds if it didn't support split touch.
9709 mWindow->setPreventSplitting(true);
9710
Arthur Hung54745652022-04-20 07:17:41 +00009711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009712 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009713 {50, 50}))
9714 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9715 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9716
9717 const MotionEvent secondFingerDownEvent =
9718 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9719 .displayId(ADISPLAY_ID_DEFAULT)
9720 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009721 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9722 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009723 .build();
9724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009725 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009726 InputEventInjectionSync::WAIT_FOR_RESULT))
9727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009728 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009729
9730 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009731 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009732}
9733
9734TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9735 // First down on second window.
9736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009738 {150, 50}))
9739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9740
9741 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9742
9743 // Second down on first window.
9744 const MotionEvent secondFingerDownEvent =
9745 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9746 .displayId(ADISPLAY_ID_DEFAULT)
9747 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009748 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9749 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009750 .build();
9751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009752 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009753 InputEventInjectionSync::WAIT_FOR_RESULT))
9754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9755 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9756
9757 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009758 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009759
9760 // Move on window.
9761 const MotionEvent secondFingerMoveEvent =
9762 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9763 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009764 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9765 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009766 .build();
9767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009768 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009769 InputEventInjectionSync::WAIT_FOR_RESULT));
9770 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9771 mWindow->consumeDragEvent(false, 50, 50);
9772 mSecondWindow->consumeMotionMove();
9773
9774 // Release the drag pointer should perform drop.
9775 const MotionEvent secondFingerUpEvent =
9776 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009780 .build();
9781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009782 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009783 InputEventInjectionSync::WAIT_FOR_RESULT));
9784 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009785 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009786 mWindow->assertNoEvents();
9787 mSecondWindow->consumeMotionMove();
9788}
9789
Arthur Hung3915c1f2022-05-31 07:17:17 +00009790TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009791 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009792
9793 // Update window of second display.
9794 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009795 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009796 mDispatcher->onWindowInfosChanged(
9797 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9798 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9799 {},
9800 0,
9801 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009802
9803 // Let second display has a touch state.
9804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009805 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009806 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9807 AINPUT_SOURCE_TOUCHSCREEN)
9808 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009809 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009810 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009811 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009812 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009813 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009814 mDispatcher->onWindowInfosChanged(
9815 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9816 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9817 {},
9818 0,
9819 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009820
9821 // Move on window.
9822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009823 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009824 ADISPLAY_ID_DEFAULT, {50, 50}))
9825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9826 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9827 mWindow->consumeDragEvent(false, 50, 50);
9828 mSecondWindow->assertNoEvents();
9829
9830 // Move to another window.
9831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009832 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009833 ADISPLAY_ID_DEFAULT, {150, 50}))
9834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9835 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9836 mWindow->consumeDragEvent(true, 150, 50);
9837 mSecondWindow->consumeDragEvent(false, 50, 50);
9838
9839 // drop to another window.
9840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009841 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009842 {150, 50}))
9843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9844 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009845 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009846 mWindow->assertNoEvents();
9847 mSecondWindow->assertNoEvents();
9848}
9849
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009850TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9851 startDrag(true, AINPUT_SOURCE_MOUSE);
9852 // Move on window.
9853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009855 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9856 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009857 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009858 .x(50)
9859 .y(50))
9860 .build()))
9861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9862 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9863 mWindow->consumeDragEvent(false, 50, 50);
9864 mSecondWindow->assertNoEvents();
9865
9866 // Move to another window.
9867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009868 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009869 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9870 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009871 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009872 .x(150)
9873 .y(50))
9874 .build()))
9875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9876 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9877 mWindow->consumeDragEvent(true, 150, 50);
9878 mSecondWindow->consumeDragEvent(false, 50, 50);
9879
9880 // drop to another window.
9881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009882 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009883 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9884 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009885 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009886 .x(150)
9887 .y(50))
9888 .build()))
9889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9890 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009891 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009892 mWindow->assertNoEvents();
9893 mSecondWindow->assertNoEvents();
9894}
9895
Linnan Li5af92f92023-07-14 14:36:22 +08009896/**
9897 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9898 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9899 */
9900TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9901 // Down on second window
9902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9904 {150, 50}))
9905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9906
9907 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9908 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9909
9910 // Down on first window
9911 const MotionEvent secondFingerDownEvent =
9912 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9913 .displayId(ADISPLAY_ID_DEFAULT)
9914 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9915 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9916 .build();
9917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9918 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9919 InputEventInjectionSync::WAIT_FOR_RESULT))
9920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9921 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9922 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9923 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9924
9925 // Start drag on first window
9926 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9927
9928 // Trigger cancel
9929 mDispatcher->cancelCurrentTouch();
9930 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9931 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9932 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9933
9934 ASSERT_TRUE(mDispatcher->waitForIdle());
9935 // The D&D finished with nullptr
9936 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9937
9938 // Remove drag window
9939 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9940
9941 // Inject a simple gesture, ensure dispatcher not crashed
9942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9943 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9944 PointF{50, 50}))
9945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9946 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9947
9948 const MotionEvent moveEvent =
9949 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9950 .displayId(ADISPLAY_ID_DEFAULT)
9951 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9952 .build();
9953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9954 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9955 InputEventInjectionSync::WAIT_FOR_RESULT))
9956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9957 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9958
9959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9960 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9961 {50, 50}))
9962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9963 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9964}
9965
Vishnu Nair062a8672021-09-03 16:07:44 -07009966class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9967
9968TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009970 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9971 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009972 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009973 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9974 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009975 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009976 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009977 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009978
9979 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009980 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009981 window->assertNoEvents();
9982
Prabir Pradhan678438e2023-04-13 19:32:51 +00009983 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9984 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9986 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009987 window->assertNoEvents();
9988
9989 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009990 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009992
Prabir Pradhan678438e2023-04-13 19:32:51 +00009993 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009994 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9995
Prabir Pradhan678438e2023-04-13 19:32:51 +00009996 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9997 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009998 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9999 window->assertNoEvents();
10000}
10001
10002TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10003 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10004 std::make_shared<FakeApplicationHandle>();
10005 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010006 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10007 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010008 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010009 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010010 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10013 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010014 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010015 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010016 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10017 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010018 mDispatcher->onWindowInfosChanged(
10019 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010020 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010021 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010022
10023 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010024 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010025 window->assertNoEvents();
10026
Prabir Pradhan678438e2023-04-13 19:32:51 +000010027 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10028 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010029 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10030 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010031 window->assertNoEvents();
10032
10033 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010034 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010035 mDispatcher->onWindowInfosChanged(
10036 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010037
Prabir Pradhan678438e2023-04-13 19:32:51 +000010038 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010039 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10040
Prabir Pradhan678438e2023-04-13 19:32:51 +000010041 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10042 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010043 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10044 window->assertNoEvents();
10045}
10046
10047TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10048 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10049 std::make_shared<FakeApplicationHandle>();
10050 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010051 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10052 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010053 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010054 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010055 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010057 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10058 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010059 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010060 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010061 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10062 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010063 mDispatcher->onWindowInfosChanged(
10064 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010065 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010066 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010067
10068 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010069 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010070 window->assertNoEvents();
10071
Prabir Pradhan678438e2023-04-13 19:32:51 +000010072 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10073 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010074 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10075 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010076 window->assertNoEvents();
10077
10078 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010079 mDispatcher->onWindowInfosChanged(
10080 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010081
Prabir Pradhan678438e2023-04-13 19:32:51 +000010082 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010083 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10084
Prabir Pradhan678438e2023-04-13 19:32:51 +000010085 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10086 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010087 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10088 window->assertNoEvents();
10089}
10090
Antonio Kantekf16f2832021-09-28 04:39:20 +000010091class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10092protected:
10093 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010094 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010095 sp<FakeWindowHandle> mWindow;
10096 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010097 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010098
10099 void SetUp() override {
10100 InputDispatcherTest::SetUp();
10101
10102 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010103 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010104 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010105 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010106 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010107 mSecondWindow =
10108 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010109 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010110 mThirdWindow =
10111 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10112 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10113 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010114
10115 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010116 mDispatcher->onWindowInfosChanged(
10117 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10118 {},
10119 0,
10120 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010121 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010122 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010123
Antonio Kantek15beb512022-06-13 22:35:41 +000010124 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010125 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010126 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010127 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10128 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010129 mThirdWindow->assertNoEvents();
10130 }
10131
10132 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10133 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010134 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010135 SECOND_DISPLAY_ID)) {
10136 mWindow->assertNoEvents();
10137 mSecondWindow->assertNoEvents();
10138 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010139 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010140 }
10141
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010142 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010143 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010144 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10145 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010146 mWindow->consumeTouchModeEvent(inTouchMode);
10147 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010148 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010149 }
10150};
10151
Antonio Kantek26defcf2022-02-08 01:12:27 +000010152TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010153 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010154 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10155 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010156 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010157}
10158
Antonio Kantek26defcf2022-02-08 01:12:27 +000010159TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10160 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010161 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010162 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010163 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010164 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010165 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010166 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010167 mWindow->assertNoEvents();
10168 mSecondWindow->assertNoEvents();
10169}
10170
10171TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10172 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010173 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010174 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010175 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010176 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010177 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010178}
10179
Antonio Kantekf16f2832021-09-28 04:39:20 +000010180TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010181 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010182 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10183 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010184 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010185 mWindow->assertNoEvents();
10186 mSecondWindow->assertNoEvents();
10187}
10188
Antonio Kantek15beb512022-06-13 22:35:41 +000010189TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10190 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10191 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10192 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010193 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010194 mWindow->assertNoEvents();
10195 mSecondWindow->assertNoEvents();
10196 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10197}
10198
Antonio Kantek48710e42022-03-24 14:19:30 -070010199TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10200 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10202 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010203 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10204 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10205
10206 // Then remove focus.
10207 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010208 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010209
10210 // Assert that caller can switch touch mode by owning one of the last interacted window.
10211 const WindowInfo& windowInfo = *mWindow->getInfo();
10212 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10213 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010214 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010215}
10216
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010217class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10218public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010219 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010220 std::shared_ptr<FakeApplicationHandle> application =
10221 std::make_shared<FakeApplicationHandle>();
10222 std::string name = "Fake Spy ";
10223 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010224 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10225 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010226 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010227 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010228 return spy;
10229 }
10230
10231 sp<FakeWindowHandle> createForeground() {
10232 std::shared_ptr<FakeApplicationHandle> application =
10233 std::make_shared<FakeApplicationHandle>();
10234 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010235 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10236 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010237 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010238 return window;
10239 }
10240
10241private:
10242 int mSpyCount{0};
10243};
10244
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010245using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010246/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010247 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10248 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010249TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010250 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010251 ScopedSilentDeath _silentDeath;
10252
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010253 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010254 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010255 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010256 ".* not a trusted overlay");
10257}
10258
10259/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010260 * Input injection into a display with a spy window but no foreground windows should succeed.
10261 */
10262TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010263 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010264 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010265
10266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010267 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010268 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10269 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10270}
10271
10272/**
10273 * Verify the order in which different input windows receive events. The touched foreground window
10274 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10275 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10276 * receive events before ones belows it.
10277 *
10278 * Here, we set up a scenario with four windows in the following Z order from the top:
10279 * spy1, spy2, window, spy3.
10280 * We then inject an event and verify that the foreground "window" receives it first, followed by
10281 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10282 * window.
10283 */
10284TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10285 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010286 auto spy1 = createSpy();
10287 auto spy2 = createSpy();
10288 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010289 mDispatcher->onWindowInfosChanged(
10290 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010291 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10292 const size_t numChannels = channels.size();
10293
Michael Wright8e9a8562022-02-09 13:44:29 +000010294 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010295 if (!epollFd.ok()) {
10296 FAIL() << "Failed to create epoll fd";
10297 }
10298
10299 for (size_t i = 0; i < numChannels; i++) {
10300 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10301 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10302 FAIL() << "Failed to add fd to epoll";
10303 }
10304 }
10305
10306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10309
10310 std::vector<size_t> eventOrder;
10311 std::vector<struct epoll_event> events(numChannels);
10312 for (;;) {
10313 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10314 (100ms).count());
10315 if (nFds < 0) {
10316 FAIL() << "Failed to call epoll_wait";
10317 }
10318 if (nFds == 0) {
10319 break; // epoll_wait timed out
10320 }
10321 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010322 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010323 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010324 channels[i]->consumeMotionDown();
10325 }
10326 }
10327
10328 // Verify the order in which the events were received.
10329 EXPECT_EQ(3u, eventOrder.size());
10330 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10331 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10332 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10333}
10334
10335/**
10336 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10337 */
10338TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10339 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010340 auto spy = createSpy();
10341 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010342 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010343
10344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010345 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10347 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10348 spy->assertNoEvents();
10349}
10350
10351/**
10352 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10353 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10354 * to the window.
10355 */
10356TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10357 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010358 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010359 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010360 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010361
10362 // Inject an event outside the spy window's touchable region.
10363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010364 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010365 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10366 window->consumeMotionDown();
10367 spy->assertNoEvents();
10368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010369 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10371 window->consumeMotionUp();
10372 spy->assertNoEvents();
10373
10374 // Inject an event inside the spy window's touchable region.
10375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010376 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010377 {5, 10}))
10378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10379 window->consumeMotionDown();
10380 spy->consumeMotionDown();
10381}
10382
10383/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010384 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010385 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010386 */
10387TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10388 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010389 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010390 auto spy = createSpy();
10391 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010392 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010393 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010394 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010395
10396 // Inject an event outside the spy window's frame and touchable region.
10397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010398 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010399 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010400 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10401 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010402 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010403}
10404
10405/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010406 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10407 * pointers that are down within its bounds.
10408 */
10409TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10410 auto windowLeft = createForeground();
10411 windowLeft->setFrame({0, 0, 100, 200});
10412 auto windowRight = createForeground();
10413 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010414 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010415 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010416 mDispatcher->onWindowInfosChanged(
10417 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010418
10419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010421 {50, 50}))
10422 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10423 windowLeft->consumeMotionDown();
10424 spy->consumeMotionDown();
10425
10426 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010427 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010428 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010429 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10430 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010431 .build();
10432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010433 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010434 InputEventInjectionSync::WAIT_FOR_RESULT))
10435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10436 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010437 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010438}
10439
10440/**
10441 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10442 * the spy should receive the second pointer with ACTION_DOWN.
10443 */
10444TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10445 auto window = createForeground();
10446 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010447 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010448 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010449 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010450
10451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010452 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010453 {50, 50}))
10454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10455 window->consumeMotionDown();
10456 spyRight->assertNoEvents();
10457
10458 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010459 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010460 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010461 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10462 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010463 .build();
10464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010465 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010466 InputEventInjectionSync::WAIT_FOR_RESULT))
10467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010468 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010469 spyRight->consumeMotionDown();
10470}
10471
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010472/**
10473 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10474 * windows should be allowed to control split touch.
10475 */
10476TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010477 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010478 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010479 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010480 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010481
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010482 auto window = createForeground();
10483 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010484
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010485 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010486
10487 // First finger down, no window touched.
10488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010489 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010490 {100, 200}))
10491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10492 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10493 window->assertNoEvents();
10494
10495 // Second finger down on window, the window should receive touch down.
10496 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010497 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010498 .displayId(ADISPLAY_ID_DEFAULT)
10499 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010500 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10501 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010502 .build();
10503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010504 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010505 InputEventInjectionSync::WAIT_FOR_RESULT))
10506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10507
10508 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010509 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010510}
10511
10512/**
10513 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10514 * do not receive key events.
10515 */
10516TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010517 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010518 spy->setFocusable(false);
10519
10520 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010521 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010522 setFocusedWindow(window);
10523 window->consumeFocusEvent(true);
10524
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010526 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10527 window->consumeKeyDown(ADISPLAY_ID_NONE);
10528
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010530 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10531 window->consumeKeyUp(ADISPLAY_ID_NONE);
10532
10533 spy->assertNoEvents();
10534}
10535
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010536using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10537
10538/**
10539 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10540 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10541 */
10542TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10543 auto window = createForeground();
10544 auto spy1 = createSpy();
10545 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010546 mDispatcher->onWindowInfosChanged(
10547 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010548
10549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010550 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10552 window->consumeMotionDown();
10553 spy1->consumeMotionDown();
10554 spy2->consumeMotionDown();
10555
10556 // Pilfer pointers from the second spy window.
10557 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10558 spy2->assertNoEvents();
10559 spy1->consumeMotionCancel();
10560 window->consumeMotionCancel();
10561
10562 // The rest of the gesture should only be sent to the second spy window.
10563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010564 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010565 ADISPLAY_ID_DEFAULT))
10566 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10567 spy2->consumeMotionMove();
10568 spy1->assertNoEvents();
10569 window->assertNoEvents();
10570}
10571
10572/**
10573 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10574 * in the middle of the gesture.
10575 */
10576TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10577 auto window = createForeground();
10578 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010579 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010580
10581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010582 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10584 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10585 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10586
10587 window->releaseChannel();
10588
10589 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10590
10591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010592 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10594 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10595}
10596
10597/**
10598 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10599 * the spy, but not to any other windows.
10600 */
10601TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10602 auto spy = createSpy();
10603 auto window = createForeground();
10604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010605 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010606
10607 // First finger down on the window and the spy.
10608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010609 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010610 {100, 200}))
10611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10612 spy->consumeMotionDown();
10613 window->consumeMotionDown();
10614
10615 // Spy window pilfers the pointers.
10616 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10617 window->consumeMotionCancel();
10618
10619 // Second finger down on the window and spy, but the window should not receive the pointer down.
10620 const MotionEvent secondFingerDownEvent =
10621 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10622 .displayId(ADISPLAY_ID_DEFAULT)
10623 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010624 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10625 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010626 .build();
10627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010628 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010629 InputEventInjectionSync::WAIT_FOR_RESULT))
10630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10631
Harry Cutts33476232023-01-30 19:57:29 +000010632 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010633
10634 // Third finger goes down outside all windows, so injection should fail.
10635 const MotionEvent thirdFingerDownEvent =
10636 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10637 .displayId(ADISPLAY_ID_DEFAULT)
10638 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010639 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10640 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10641 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010642 .build();
10643 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010644 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010645 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010646 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010647
10648 spy->assertNoEvents();
10649 window->assertNoEvents();
10650}
10651
10652/**
10653 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10654 */
10655TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10656 auto spy = createSpy();
10657 spy->setFrame(Rect(0, 0, 100, 100));
10658 auto window = createForeground();
10659 window->setFrame(Rect(0, 0, 200, 200));
10660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010661 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010662
10663 // First finger down on the window only
10664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010666 {150, 150}))
10667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10668 window->consumeMotionDown();
10669
10670 // Second finger down on the spy and window
10671 const MotionEvent secondFingerDownEvent =
10672 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10673 .displayId(ADISPLAY_ID_DEFAULT)
10674 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010675 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10676 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010677 .build();
10678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010679 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010680 InputEventInjectionSync::WAIT_FOR_RESULT))
10681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10682 spy->consumeMotionDown();
10683 window->consumeMotionPointerDown(1);
10684
10685 // Third finger down on the spy and window
10686 const MotionEvent thirdFingerDownEvent =
10687 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10688 .displayId(ADISPLAY_ID_DEFAULT)
10689 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010690 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10691 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10692 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010693 .build();
10694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010695 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010696 InputEventInjectionSync::WAIT_FOR_RESULT))
10697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10698 spy->consumeMotionPointerDown(1);
10699 window->consumeMotionPointerDown(2);
10700
10701 // Spy window pilfers the pointers.
10702 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010703 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10704 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010705
10706 spy->assertNoEvents();
10707 window->assertNoEvents();
10708}
10709
10710/**
10711 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10712 * other windows should be canceled. If this results in the cancellation of all pointers for some
10713 * window, then that window should receive ACTION_CANCEL.
10714 */
10715TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10716 auto spy = createSpy();
10717 spy->setFrame(Rect(0, 0, 100, 100));
10718 auto window = createForeground();
10719 window->setFrame(Rect(0, 0, 200, 200));
10720
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010721 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010722
10723 // First finger down on both spy and window
10724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010726 {10, 10}))
10727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10728 window->consumeMotionDown();
10729 spy->consumeMotionDown();
10730
10731 // Second finger down on the spy and window
10732 const MotionEvent secondFingerDownEvent =
10733 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10734 .displayId(ADISPLAY_ID_DEFAULT)
10735 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010736 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10737 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010738 .build();
10739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010740 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010741 InputEventInjectionSync::WAIT_FOR_RESULT))
10742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10743 spy->consumeMotionPointerDown(1);
10744 window->consumeMotionPointerDown(1);
10745
10746 // Spy window pilfers the pointers.
10747 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10748 window->consumeMotionCancel();
10749
10750 spy->assertNoEvents();
10751 window->assertNoEvents();
10752}
10753
10754/**
10755 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10756 * be sent to other windows
10757 */
10758TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10759 auto spy = createSpy();
10760 spy->setFrame(Rect(0, 0, 100, 100));
10761 auto window = createForeground();
10762 window->setFrame(Rect(0, 0, 200, 200));
10763
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010764 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010765
10766 // First finger down on both window and spy
10767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010768 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010769 {10, 10}))
10770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10771 window->consumeMotionDown();
10772 spy->consumeMotionDown();
10773
10774 // Spy window pilfers the pointers.
10775 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10776 window->consumeMotionCancel();
10777
10778 // Second finger down on the window only
10779 const MotionEvent secondFingerDownEvent =
10780 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10781 .displayId(ADISPLAY_ID_DEFAULT)
10782 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010783 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10784 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010785 .build();
10786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010787 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010788 InputEventInjectionSync::WAIT_FOR_RESULT))
10789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10790 window->consumeMotionDown();
10791 window->assertNoEvents();
10792
10793 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10794 spy->consumeMotionMove();
10795 spy->assertNoEvents();
10796}
10797
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010798/**
10799 * A window on the left and a window on the right. Also, a spy window that's above all of the
10800 * windows, and spanning both left and right windows.
10801 * Send simultaneous motion streams from two different devices, one to the left window, and another
10802 * to the right window.
10803 * Pilfer from spy window.
10804 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10805 */
10806TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10807 sp<FakeWindowHandle> spy = createSpy();
10808 spy->setFrame(Rect(0, 0, 200, 200));
10809 sp<FakeWindowHandle> leftWindow = createForeground();
10810 leftWindow->setFrame(Rect(0, 0, 100, 100));
10811
10812 sp<FakeWindowHandle> rightWindow = createForeground();
10813 rightWindow->setFrame(Rect(100, 0, 200, 100));
10814
10815 constexpr int32_t stylusDeviceId = 1;
10816 constexpr int32_t touchDeviceId = 2;
10817
10818 mDispatcher->onWindowInfosChanged(
10819 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10820
10821 // Stylus down on left window and spy
10822 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10823 .deviceId(stylusDeviceId)
10824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10825 .build());
10826 leftWindow->consumeMotionEvent(
10827 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10828 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10829
10830 // Finger down on right window and spy - but spy already has stylus
10831 mDispatcher->notifyMotion(
10832 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10833 .deviceId(touchDeviceId)
10834 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10835 .build());
10836 rightWindow->consumeMotionEvent(
10837 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010838 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010839
10840 // Act: pilfer from spy. Spy is currently receiving touch events.
10841 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010842 leftWindow->consumeMotionEvent(
10843 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010844 rightWindow->consumeMotionEvent(
10845 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10846
10847 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10848 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10849 .deviceId(stylusDeviceId)
10850 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10851 .build());
10852 mDispatcher->notifyMotion(
10853 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10854 .deviceId(touchDeviceId)
10855 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10856 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010857 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010858
10859 spy->assertNoEvents();
10860 leftWindow->assertNoEvents();
10861 rightWindow->assertNoEvents();
10862}
10863
Prabir Pradhand65552b2021-10-07 11:23:50 -070010864class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10865public:
10866 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10867 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10868 std::make_shared<FakeApplicationHandle>();
10869 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010870 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10871 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010872 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010873 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010874 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010875 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010876 overlay->setTrustedOverlay(true);
10877
10878 std::shared_ptr<FakeApplicationHandle> application =
10879 std::make_shared<FakeApplicationHandle>();
10880 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010881 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10882 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010883 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010884 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010885
10886 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010887 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010888 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010889 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010890 return {std::move(overlay), std::move(window)};
10891 }
10892
10893 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010894 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010895 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010896 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010897 }
10898
10899 void sendStylusEvent(int32_t action) {
10900 NotifyMotionArgs motionArgs =
10901 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10902 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010903 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010904 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010905 }
10906};
10907
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010908using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10909
10910TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010911 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010912 ScopedSilentDeath _silentDeath;
10913
Prabir Pradhand65552b2021-10-07 11:23:50 -070010914 auto [overlay, window] = setupStylusOverlayScenario();
10915 overlay->setTrustedOverlay(false);
10916 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010917 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10918 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010919 ".* not a trusted overlay");
10920}
10921
10922TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10923 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010924 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010925
10926 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10927 overlay->consumeMotionDown();
10928 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10929 overlay->consumeMotionUp();
10930
10931 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10932 window->consumeMotionDown();
10933 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10934 window->consumeMotionUp();
10935
10936 overlay->assertNoEvents();
10937 window->assertNoEvents();
10938}
10939
10940TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10941 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010942 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010943 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010944
10945 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10946 overlay->consumeMotionDown();
10947 window->consumeMotionDown();
10948 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10949 overlay->consumeMotionUp();
10950 window->consumeMotionUp();
10951
10952 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10953 window->consumeMotionDown();
10954 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10955 window->consumeMotionUp();
10956
10957 overlay->assertNoEvents();
10958 window->assertNoEvents();
10959}
10960
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010961/**
10962 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10963 * The scenario is as follows:
10964 * - The stylus interceptor overlay is configured as a spy window.
10965 * - The stylus interceptor spy receives the start of a new stylus gesture.
10966 * - It pilfers pointers and then configures itself to no longer be a spy.
10967 * - The stylus interceptor continues to receive the rest of the gesture.
10968 */
10969TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10970 auto [overlay, window] = setupStylusOverlayScenario();
10971 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010972 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010973
10974 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10975 overlay->consumeMotionDown();
10976 window->consumeMotionDown();
10977
10978 // The interceptor pilfers the pointers.
10979 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10980 window->consumeMotionCancel();
10981
10982 // The interceptor configures itself so that it is no longer a spy.
10983 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010984 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010985
10986 // It continues to receive the rest of the stylus gesture.
10987 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10988 overlay->consumeMotionMove();
10989 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10990 overlay->consumeMotionUp();
10991
10992 window->assertNoEvents();
10993}
10994
Prabir Pradhan5735a322022-04-11 17:23:34 +000010995struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010996 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010997 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010998 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10999 std::unique_ptr<InputDispatcher>& mDispatcher;
11000
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011001 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011002 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11003
11004 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011005 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011006 ADISPLAY_ID_DEFAULT, {100, 200},
11007 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11008 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11009 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11010 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11011 }
11012
11013 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011014 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011015 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011016 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011017 mPolicyFlags);
11018 }
11019
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011020 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011021 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11022 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011023 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11024 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011025 window->setOwnerInfo(mPid, mUid);
11026 return window;
11027 }
11028};
11029
11030using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11031
11032TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011033 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011034 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011035 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011036
11037 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11038 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11039 window->consumeMotionDown();
11040
11041 setFocusedWindow(window);
11042 window->consumeFocusEvent(true);
11043
11044 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11045 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11046 window->consumeKeyDown(ADISPLAY_ID_NONE);
11047}
11048
11049TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011050 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011051 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011052 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011053
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011054 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011055 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11056 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11057
11058 setFocusedWindow(window);
11059 window->consumeFocusEvent(true);
11060
11061 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11062 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11063 window->assertNoEvents();
11064}
11065
11066TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011067 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011068 auto window = owner.createWindow("Owned window");
11069 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011070 spy->setSpy(true);
11071 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011072 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011073
11074 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11075 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11076 spy->consumeMotionDown();
11077 window->consumeMotionDown();
11078}
11079
11080TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011081 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011082 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011083
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011084 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011085 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011086 randosSpy->setSpy(true);
11087 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011088 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011089
11090 // The event is targeted at owner's window, so injection should succeed, but the spy should
11091 // not receive the event.
11092 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11093 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11094 randosSpy->assertNoEvents();
11095 window->consumeMotionDown();
11096}
11097
11098TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011099 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011100 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011101
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011102 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011103 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011104 randosSpy->setSpy(true);
11105 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011106 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011107
11108 // A user that has injection permission can inject into any window.
11109 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011110 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011111 ADISPLAY_ID_DEFAULT));
11112 randosSpy->consumeMotionDown();
11113 window->consumeMotionDown();
11114
11115 setFocusedWindow(randosSpy);
11116 randosSpy->consumeFocusEvent(true);
11117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011118 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011119 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11120 window->assertNoEvents();
11121}
11122
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011123TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011124 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011125 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011126
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011127 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011128 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011129 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11130 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011131 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011132
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011133 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011134 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11135 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11136 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011137 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011138}
11139
Garfield Tane84e6f92019-08-29 17:28:41 -070011140} // namespace android::inputdispatcher